여러 파일에서 공통점/패턴 찾기

여러 파일에서 공통점/패턴 찾기

수백 또는 수천 개의 파일이 있는 폴더가 있고 모두 다음 스키마의 이름을 따서 명명되었다고 가정해 보겠습니다.

<random number of variable length>_<date code in YYYYMMDD format>.jpg

예:

73923_20180927.jpg
4457582_20180927.jpg
   ...
18733557_20190401.jpg
23573_20190401.jpg
   ...

내 bash 스크립트에서 기대하는 것은 해당 날짜 코드 목록을 인쇄하는 것입니다.

20180927
20190401
   ...

그것은 더 쉬운 작업처럼 들립니다. 스키마는 항상 동일하므로 파일 이름 중 필요한 부분만 인쇄하기 위해 문자열 조작을 적용하는 방법을 이미 달성했습니다. 그러나 각 날짜를 한 번만 인쇄하는 방법을 여전히 파악 중입니다.

이것에서 깔끔한 방법이 있습니까?

답변1

파일 이름이 모두 패턴과 일치한다고 가정합니다 ./*_*.jpg.

for name in ./*_*.jpg; do
    name=${name##*_}              # 4457582_20180927.jpg --> 20180927.jpg
    printf '%s\n' "${name%.jpg}"  # 20180927.jpg --> 20180927
done | sort -u

이는 모든 이름을 반복합니다. 그런 다음 각 이름에 대해 일치하는 가장 긴 접두사 문자열을 제거합니다 *_. 그런 다음 접미사가 제거된 나머지 문자열을 출력합니다 .jpg.

그런 다음 모든 문자열은 마지막에 고유한 문자열 목록만 출력되는 방식으로 정렬됩니다.

디렉토리가 비어 있을 위험이 있는 경우 nullglob루프( shopt -s nullglob) 앞에 쉘 옵션을 설정해야 합니다. 이렇게 하면 NET에서 확장되지 않은 globbing 패턴으로 한 번 실행되는 대신 루프가 전혀 실행되지 않게 됩니다 $name.


특별한 이유 없이 다음을 수행하는 방법은 다음과 같습니다 sort.

declare -A skip=()

for name in ./*_*.jpg; do
    key=${name##*_}    # 4457582_20180927.jpg --> 20180927.jpg
    key=${key%.jpg}    # 20180927.jpg --> 20180927
    if [[ ! -v skip[$key] ]]; then
        printf '%s\n' "$key"
        skip[$key]=1
    fi
done

여기서는 연관 배열의 키로 이미 출력된 문자열을 추적합니다 skip. 배열의 키에 해당하는 문자열은 출력되지 않습니다.

답변2

실제로 부적절한 파일 이름이 없다고 가정하고 해당 디렉토리에서 실행하십시오.

ls -U | awk '-F[_.]' '{ print $2 }' | sort | uniq

관련 정보