디렉토리에서 누락된 파일을 찾고 인쇄하는 방법은 무엇입니까?

디렉토리에서 누락된 파일을 찾고 인쇄하는 방법은 무엇입니까?

.grid로 끝나는 파일이 포함된 상위 디렉터리의 모든 디렉터리를 찾아서 나열하고 싶습니다./work/user/folder1/*/*

find /work/user/folder1/*/*/ '!' -mindepth 1 -maxdepth 1 -name *.grid

다음으로 하고 싶은 일은 .grid로 끝나는 파일이 누락된 모든 디렉터리를 찾는 것입니다. 기본적으로 누락된 폴더를 인쇄하는 명령을 원합니다.

어떻게 해야 하나요?

답변1

find전화를 걸 때 사용하세요 find!

find . -type d \( -exec sh -c 'cd "$0"; find . \( -name . -o -prune \) -name "*.grid" | grep -q .' {} \; -o -print \)

이것은 POSIX를 준수합니다. 이 답변에 감사드립니다.

또한 이는 파일이나 디렉터리 이름에 공백, 특수 문자 또는 개행 문자가 있는지 여부에 관계없이 작동합니다. :)

(참고: 만약 당신이하다디렉토리 이름에 특수 문자나 개행 문자가 포함된 경우 -print최종 main을 디렉토리에서 원하는 대로 변경해야 합니다. 왜냐하면 .만 사용하면 결과 인쇄 목록을 안전하게 구문 분석할 수 없기 때문입니다 -print. )

다음은 가독성을 높이기 위해 오해의 소지가 있는 개행 문자가 추가된 버전입니다.

find . -type d \
  \( \
    -exec sh -c '
      cd "$0";
      find . \( -name . -o -prune \) -name "*.grid" |
        grep -q .
    ' {} \; \
    -o -print \
  \)

답변2

1단계.) 적용 가능한 모든 디렉터리 목록을 만들고 영숫자순으로 정렬한 다음 중복 항목이 없는지 확인합니다. 임시 파일에 목록을 저장합니다.

find /work/user/folder1/ [...] -type d | sort | uniq > all_directories.txt

2단계.) 모든 파일 목록을 만듭니다 *.grid.

find /work/user/folder1/ [...] -name *.grid > grid_files.txt

3단계.) 파일 목록을 살펴보고 *.grid각 파일의 디렉터리 이름을 가져온 다음 다시 중복 항목이 없는지 확인하세요.

while read FILENAME
do
    echo $(dirname "$FILENAME")
done < grid_files.txt | sort | uniq > dirs_with_gridfiles.txt

4단계.) 두 목록을 함께 실행하고 결과를 다시 정렬합니다. 이제 *.grid파일이 포함된 디렉터리가 나열되어야 합니다.정확히각각 두 번씩, 디렉터리에 *.grid파일이 없습니다.정확히각각 한 번씩. 따라서 uniq중복되지 않은 행만 보고 하도록 알 수 있습니다 .

cat all_directories.txt dirs_with_gridfiles.txt | sort | uniq -u > dirs_with_no_gridfile.txt

당신은 그것을 얻습니다.

답변3

이는 2단계 솔루션입니다. 전반적으로 프로세스는 다음과 같습니다.

  1. *.grid기본 파일 이름과 목록을 제거하여 경로의 모든 파일을 찾습니다 uniq. 그러면 하나 이상의 파일이 포함된 모든 디렉토리의 목록이 제공됩니다 *.grid.

$ find /work/user/folder1/*/*/ -type f -name *.grid | sed -e 's-[^/]*$--' | sort | uniq > grid-dirs.txt

  1. 경로에서 모든 디렉터리를 찾고 grep1단계에서 찾은 디렉터리를 필터링하는 데 사용합니다. 그러면 *.grid파일이 포함되어 있지 않은 모든 디렉터리 목록이 제공됩니다 .

$ find /work/user/folder1/*/*/ -type d | grep -Fvxf grid-dirs.txt

예를 들어 다음과 같이 가정합니다.

$ find /work
/work
/work/user
/work/user/folder1
/work/user/folder1/AA
/work/user/folder1/AA/AA
/work/user/folder1/AA/DD
/work/user/folder1/AA/CC
/work/user/folder1/AA/BB
/work/user/folder1/AA/BB/foo.grid

1단계 이후에는 grid-dirs.txt다음과 같습니다.

/work/user/folder1/AA/BB/

2단계의 출력은 다음과 같습니다.

$ find /work/user/folder1/*/*/ -type d | grep -Fvxf grid-dirs.txt
/work/user/folder1/AA/AA/
/work/user/folder1/AA/CC/
/work/user/folder1/AA/DD/

답변4

Bash v4(또는 그 이상)를 사용하는 경우 *.grid루프의 모든 파일과 모든 디렉터리를 통과하여 파일이 있는 디렉터리와 없는 디렉터리를 나열하는 내부 루프도 찾을 수 있다고 생각합니다. Bash v4의 경우 일반적으로 비활성화된 옵션 중 하나를 사용합니다.

(
# 'globstar' enables '**' expansions, which instructs
# the shell to search all and below recursively
shopt -s globstar

# Note that '**' is implicitly recursive, no need to specify
# depth. If you do want to specify precise depth, then use a
# '*/' for each wanted depth, like '*/*/*/' for 3 depths
for f in /work/user/folder1/**/*.grid; do
    f="${f##*/}"  # strip directory from found name
    printf '\nNow looking for: %s\n' "$f"
    # A simple '**/' returns directories only
    for d in /work/user/folder1/**/; do
        # simple existence test
        [ -e "${d}${f}" ] && \
            printf '    present in %s\n' "$d" || \
            printf 'not present in %s\n' "$d"
    done
done
)

불행히도 **구문은 POSIX가 아닙니다.

그러나 검색해야 하는 정확한 깊이를 알고 있는 경우 해당 명령을 제거 shopt하고 각 명령을 **/반복으로 표현된 정확한 깊이로 변환하면 */POSIX 셸에서도 잘 작동합니다.

관련 정보