특정 파일만 포함된 디렉토리를 찾는 방법

특정 파일만 포함된 디렉토리를 찾는 방법

쓸모없는 파일(예: ,,,,)이 포함된 여러 디렉터리가 있습니다 *.tmp.desktop.iniThumbs.db.picasa.ini

모든 드라이브를 검색하여 일부 파일만 포함된 디렉터리를 찾으려면 어떻게 해야 합니까?

답변1

, 및/또는 이외의 이름이 없는 *.tmp모든 desktop.ini디렉토리 Thumbs.db를 찾으려면 다음을 수행하십시오 .picasa.ini.

find . -type d -exec bash -O dotglob -c '
    for dirpath do
        ok=true
        seen_files=false
        set -- "$dirpath"/*
        for name do
            [ -d "$name" ] && continue  # skip dirs
            seen_files=true
            case "${name##*/}" in
                *.tmp|desktop.ini|Thumbs.db|.picasa.ini) ;; # do nothing
                *) ok=false; break
            esac
        done

        "$seen_files" && "$ok" && printf "%s\n" "$dirpath"
    done' bash {} +

find이는 현재 디렉토리 아래(포함)의 디렉토리를 찾아 쉘 스크립트에 전달하는 데 사용됩니다 .

쉘 스크립트는 주어진 디렉토리 경로를 반복하고 각 디렉토리 경로에 대해 *그 안에서 확장됩니다( 숨겨진 이름을 캡처하도록 dotglob쉘 옵션을 설정하십시오 ).bash

그런 다음 결과 이름 목록을 반복하여 우리가 찾으려는 특정 패턴 및 이름과 일치시킵니다(디렉터리 무시). 혹시 찾으신다면다른이름이 목록과 일치하지 않으면 (from has was ) ok로 설정되고 내부 루프에서 벗어납니다.falsetrue

다음 유형을 제외한 모든 유형의 파일을 보면 이 seen_files변수는 다음과 같습니다.true목차(또는디렉토리에 대한 심볼릭 링크). 이 변수는 다른 하위 디렉터리만 포함하는 하위 디렉터리를 보고하는 것을 방지하는 데 도움이 됩니다.

$seen_files그런 다음 and $ok( true또는 ) 을 실행 false하고 둘 다인 경우 true해당 디렉터리에 최소한 하나의 일반 파일이 포함되어 있음을 의미하며,목록에 있는 파일 이름만 포함, 디렉토리의 경로 이름을 인쇄합니다.

바꾸다

set -- "$dirpath"/*
for name do

당신은 분명히 이것을 할 수 있습니다

for name in "$dirpath"/*; do

대신에.

시험:

$ tree
.
`-- dir
    |-- Thumbs.db
    `-- dir
        |-- file.tmp
        `-- something

2 directories, 3 files

( find여기서 명령이 실행되어 출력이 생성됩니다...)

./dir

즉, 디렉터리 ./dir에는 목록의 이름(디렉터리 무시)만 포함되고 ./dir/dir다른 콘텐츠도 포함됩니다.

[ -d "$name" ] && continue코드에서 제거하면 목록( )에 없는 이름이 ./dir포함되어 있으므로 디렉터리를 찾을 수 없습니다 .dir

답변2

find, xargs, ls, sed, wc 및 awk 명령의 조합을 사용하면 작동합니다.

find . -type f \( -iname "desktop.ini" -o -name "thumb.db" \)  -printf %h\\0 | xargs -0 -I "{}" sh -c 'printf "{}\t"; ls -l "{}" | sed -n "1!p" | wc -l' | awk '$2 == "1" {print $0}'

설명하다:

  • find .현재 디렉토리에서 찾기
  • -type f파일만 찾기
  • \( -iname "desktop.ini" -o -name "thumb.db" \)여기서 파일 이름은 "desktop.ini" 또는 "thumb.db"이며 대소문자를 구분하지 않습니다.
  • printf %h\\0파일 이름 + ASCII NUL의 선두 디렉토리를 인쇄합니다.
  • xargs -0 -I "{}" sh -c 'printf "{}\t"; ls -l "{}"출력 디렉터리를 인쇄하고 ls -l각 디렉터리에서 실행
  • sed -n "1!p" | wc -l'전체 파일과 디렉터리가 포함된 첫 번째 줄을 제외하고 ls -l줄 수를 계산합니다.
  • awk '$2 == "1" {print $0}'개수가 "1"과 같으면 해당 줄을 인쇄합니다.

답변3

파일이나 폴더를 이름으로 지정하는 것이 좋습니다. 예를 들면 다음과 같습니다.

find ${HOME} -type f -iname thumbs.db -print0 | xargs -0 --no-run-if-empty rm

( ) "thumbs.db" -type f라는 이름의 모든 파일을 찾아서 ( ) 삭제합니다 ( ) .-inameiinamerm

다음과 같은 파일 이름 패턴을 사용할 수 있습니다.

find ${HOME} -type f -iname '*.tmp' -print0 | xargs -0 --no-run-if-empty rm

경고하다:입력하신 내용에 주의하시기 바랍니다. 요청 없이 삭제될 수 있습니다.

정기적으로 백업하십시오. 정리 프로세스를 시작하기 전에 좋은 시간이 될 수 있습니다!

무엇을 기대해야 할지 알고 싶다면 rm작업을 수행하기 전에 파일 목록을 살펴보십시오. 예를 들면 다음과 같습니다.

find ${HOME} -type f -iname thumbs.db -print0 | xargs -0 --no-run-if-empty ls -l

답변4

GNU find및 GNU를 사용하면 모든 파일을 보고하고 일치시킬 awk수 있습니다 .findawk

find . -depth -type d -printf '%p/\0' -o -printf '%p\0' |
  gawk -F/ -v OFS=/ -v RS='\0' -v IGNORECASE=1 '
    /\/$/ {
     NF--
     if (good[$0] == 0 && bad[$0] > 0) print
     next
    }
    {
      name = $NF
      NF--
      if (name ~ /^(.*\.tmp|desktop\.ini|Thumbs\.db|\.picasa\.ini)$/)
        bad[$0]++
      else
        good[$0]++
    }'

빈 디렉터리도 포함하려면 제거하세요 && bad[$0] > 0. 대소문자를 구분하려면 제거하세요 -v IGNORECASE=1.

관련 정보