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)