손실된 파일을 검색할 수 있는 방법이 필요합니다

손실된 파일을 검색할 수 있는 방법이 필요합니다

다음과 같은 이름의 디렉토리에 이미지 세트가 있는 경우:

filename.jpg
filename.jpg.webp

filename-150x150.jpg

filename-250x250.jpg
filename-250x250.jpg.webp

filename-600x600.jpg

filename-800x800.jpg
filename-800x800.jpg.webp

find버전 없이 모든 파일을 반환하기 위해 명령(또는 다른 명령)을 사용하는 방법이 있습니까 .webp? 따라서 이 예에서는 150x150 및 600x600 파일을 반환합니다.

답변1

다양한 변형에서 발견되는 다음 파일 이름 중 하나를 사용하려는 경우 다음을 확인하십시오.출력의 파일 이름은 구문 분석되지 않습니다.. 대신에,printf당신이 해야 할 일로 대체하세요. 이렇게 하면 공백과 와일드카드가 포함된 파일 이름과 관련된 문제를 피할 수 있습니다. 또한 코드를 더욱 효율적이고 아름답게 만들어 궁극적으로 더 건강한 라이프 스타일과 더 나은 친구로 이어질 것입니다.

바라보다찾기 결과를 반복하는 것이 왜 나쁜 습관입니까?

.webp내가 만든 한 가지 가정은 해당 파일을 생성하려고 하기 때문에 해당 파일이 없는 JPEG 이미지를 찾고 싶다는 것입니다 .webp. 이것이 바로 ("이름이 존재하고 일반 파일이거나 해당 파일에 대한 심볼릭 링크입니다") 또는 ("이름이 존재하며 읽을 수 있습니다") 테스트 -e대신 아래의 ("이름이 존재합니다") 테스트를 사용하는 이유입니다 .-f-r

.webp이름이 있으면존재하다, 디렉토리나 문자 특수 파일이거나 기타 색다른 파일 유형인 경우(테스트는 -f다음과 같습니다.잘못된) 또는 읽을 수 없는 경우(테스트가 -r잘못된 경우) 파일 방법 .webp에 따라 기존 내용을 덮어쓰거나 디렉터리에 넣거나 권한 오류가 발생하므로 파일 생성에 문제가 발생합니다. .webp창조.


간단한 루프를 사용하여 일치하는 이름을 반복 *.jpg하고 파일에 해당하지 않는 이름을 인쇄합니다 *.jpg.webp.

for name in *.jpg; do
    [ -f "$name" ] && [ ! -e "$name.webp" ] && printf '%s\n' "$name"
done

목록에 이름을 저장하려면 위치 인수 목록을 사용할 수 있습니다.

set --
for name in *.jpg; do
    [ -f "$name" ] && [ ! -e "$name.webp" ] && set -- "$@" "$name"
done

printf 'Needs webp fixed: %s\n' "$@"

에서는 bash명명된 배열에 이름을 저장할 수 있습니다.

needs_webp=()
for name in *.jpg; do
    [ -f "$name" ] && [ ! -e "$name.webp" ] && needs_webp+=( "$name" )
done

printf 'Needs webp fixed: %s\n' "${needs_webp[@]}"

셸에서는 zshglobbing 자체에서 이름을 테스트할 수 있습니다.*.webp

printf 'Needs webp fixed: %s\n' *.jpg(.e['[ ! -e $REPLY.webp ]'])

여기서 .패턴 끝에 있는 in 와일드카드 한정자는 (디렉터리 등이 아닌) 일반 파일만 일치하는지 확인하고 현재 이름이 결과 목록에 포함되어야 하는지 e['[ ! -e $REPLY.webp ]']확인하는 테스트 역할을 합니다 .$REPLY


그리고 find:

find . -name '*.jpg' -type f ! -exec test -e {}.webp \; -print

현재 디렉터리나 아래 디렉터리에서 패턴과 일치하는 이름을 가진 일반 파일을 찾고 , 같은 이름에 해당하지만 끝에 추가된 *.jpg파일이 없으면 해당 이름을 인쇄합니다..webp

{}그러나 POSIX 표준이 다른 문자열과 연결되는 경우(위에 표시된 대로) POSIX 표준은 해당 문자열이 현재 파일 이름으로 대체된다는 것을 보장하지 않습니다. 그래서 그것이 효과가 있는지 확인하고 싶다면 다음과 같이 말할 것입니다.

find . -name '*.jpg' -type f -exec sh -c '
    for name do
        [ -e "$name.webp" ] && printf "%s\n" "$name"
    done' {} +

보시다시피 이제 우리는 이 답변의 첫 번째 루프로 어느 정도 돌아왔습니다. 이제 유일한 차이점은 find현재 디렉터리나 해당 하위 디렉터리에서 재귀적으로 기존 경로 이름을 제공하는 것입니다.

답변2

이것은 나에게 효과적입니다.

find . -not -name '*.webp' -exec test ! -r {}.webp \; -exec echo {} \;

로 끝나지 않는 모든 이름을 찾습니다 .webp. 찾은 각 이름에 대해 .webp동일한 이름과 확장자를 가진 파일이 존재하는지 테스트합니다. 그렇지 않은 경우 파일을 인쇄하십시오.

두 번째 것은 -exec첫 번째가 성공적으로 반환된 경우, 즉 해당 .webp확장 파일이 존재하지 않는 경우에만 실행된다는 점은 주목할 가치가 있습니다.

파일 목록을 실행하면 내 출력은 다음과 같습니다.

./filename-600x600.jpg
./filename-150x150.jpg

답변3

루프를 사용해 다음을 시도해 보세요.

# to expand to null string in empty directories¹
shopt -s nullglob
# loop over the jpg files
for i in *.jpg; do 
  # test if there's a file that matches the name but with '.webp' extension
  # if there's a match don't do anything and continue with the loop
 [[ -f "$i.webp" ]] && continue || \
 # else perform an operation
 echo "$i"
done

filename-150x150.jpg
filename-600x600.jpg

^4.3.2 내장 상점

빈 공

    설정된 경우 Bash는 파일과 일치하지 않는 파일 이름 패턴이   
자신이 아닌 빈 문자열로 확장되도록 허용합니다.

관련 정보