while 루프에서 일치하지 않는 파일 이름 표시

while 루프에서 일치하지 않는 파일 이름 표시

files.txt일부 파일 이름이 포함된 이라는 파일이 있습니다 . 파일을 읽고 a를 실행하여 find찾은 파일 이름을 반환하는 명령이 있습니다 . 그 반대로 수행하는 방법이 궁금합니다. 내가 원하는 것은 찾지 못한 파일 이름을 표시하는 것입니다.

예:

$ ls
file1  file2  file3  files.txt
$ cat files.txt
file1
file2
file3
file4
$ while read x; do (find . -iname "$x"); done < files.txt
./file1
./file2
./file3

file4이 예에서는 파일 이름이 .txt에 있지만 폴더에 없기 때문에 결과에 표시되기를 원합니다 .

답변1

사용 grep(현재 폴더의 파일에 대해 이름에 개행 문자가 포함되어 있지 않다고 가정):

$ grep -v -i -F -x -f <(printf '%s\n' *) files.txt
file4

옵션:

  • -v일치를 취소하고 일치하지 않는 행을 선택합니다.
  • -f printf '%s\n' *현재 디렉토리의 파일을 나열하고 grep.
  • -F패턴을 고정 문자열로 해석합니다(정규 표현식 대신).
  • -x전체 라인과 일치
  • -i대소문자를 구분하지 않는 일치(당신과 같은 -iname).

답변2

사용 find:

while IFS= read -r name; do
    if [ -z "$(find . -iname "$name")" ]; then
        printf 'Not found: %s\n' "$name"
    fi
done <files.txt

이 루프는 파일에서 한 번에 하나의 파일 이름을 읽고 files.txt현재 디렉터리 아래의 전체 계층 구조에서 해당 이름을 대소문자를 구분하지 않고 검색합니다. 이름을 찾을 수 없으면( find아무 것도 출력되지 않음) 메시지가 표시됩니다.

find명령이 일반 파일(디렉토리 등이 아닌)만 찾 도록 하려면 -type f명령에 추가하십시오.

답변3

find깊이가 디렉터리인 경우 다음을 사용하는 대신 이 작업을 수행할 수 있습니다.

while IFS= read -r file; do 
  [[ -f "${file}" ]] && echo "${file} exists" \
  || echo "$file doesn't exist"; 
done < files.txt

답변4

그리고 zsh:

set -o extendedglob # best in ~/.zshrc
files=(*(ND))
list=(${(f)"$(<files.txt)"})

not_found=(${list:#(#i)(${(~j[|])files})})
if (($#not_found)); then
  echo "Not found:"
  printf ' - %q\n' $not_found
fi

not_in_list=(${files:#(#i)(${(~j[|])list})})
if (($#not_in_list)); then
  echo "Unexpected files (not in files.txt):"
  printf ' - %q\n' $not_in_list
fi

현재 디렉터리(배열)에 있는 파일 목록과 (배열)에 있는 파일 목록 $files사이에서 대소문자를 구분하지 않고 빼기를 수행합니다 .files.txt$list

zsh실제로 배열 빼기 연산자( )가 있지만 ${array1:|array2}대소문자를 구분하지 않으려면 여기서는 사용할 수 없습니다.

대신 ${array:#pattern}요소로 확장되는 연산자를 사용합니다.$array 와는 별개로일치합니다 pattern.

여기의 패턴은 |( )를 사용하고 대소문자를 구분하지 않는 일치를 위해 연산자를 사용하여 j[|]다른 배열의 요소를 연결함으로써 구축됩니다.extendedglob (#i)

관련 정보