파일을 가져오고 해당 파일에 대해 일부 작업을 수행하기 위해 하위 디렉터리를 반복합니다.

파일을 가져오고 해당 파일에 대해 일부 작업을 수행하기 위해 하위 디렉터리를 반복합니다.

폴더를 반복하여 파일을 가져오고 해당 파일에 대한 작업을 수행하여 파일과 이름이 같은 텍스트 파일로 출력을 리디렉션하려고 합니다. 나는 "찾기"를 사용해 보았습니다 -

cd /filepath/orig/v1

for dir in $(find . -type d); do
  cd $dir
  for subdir in $(find . -type d); do
          cd $subdir
          for file in `ls`; do
                  echo $file
                  touch $file.txt
                  cdo info $file > $file.txt
          done
  done
done

그러나 이것은 작동하지 않습니다. 디렉토리 구조는 - /filepath/orig/v1/level1/level2/file.nc와 유사하지만 하위 디렉토리는 2개 이상의 레벨을 가질 수 있습니다.

답변1

이를 위해서는 루프가 필요하지 않습니다. 찾기가 모든 것을 할 것입니다.

find . -type f ! -name '*.txt' -print -exec sh -c 'cdo info {} > {}.txt' \;

이렇게 하면 기존 .txt 파일이 손상되므로 "*.txt 아님"보다 더 구체적인 파일 이름 필터를 사용해야 할 수도 있습니다.

답변2

2단계 고정 디렉터리 구조가 있는 경우:

shopt -s dotglob nullglob

for pathname in /filepath/orig/v1/*/*; do
    [[ $pathname == *.txt ]] && continue

    printf 'Processing "%s"\n' "$pathname" >&2
    
    cdo info "$pathname" >"$pathname.txt"
done

먼저 쉘 옵션을 활성화 dotglob합니다 nullglob. 이러한 셸 옵션을 사용하면 와일드카드 패턴이 숨겨진 이름( dotglob)과 일치하고 패턴이 일치하는지 확인할 수 있습니다.아니요일치 항목이 완전히 제거됩니다( ; 이는 일치하는 이름이 없으면 nullglob루프가 단일 반복을 실행하지 않음을 의미합니다)./filepath/orig/v1/*/*

루프에서 이미 끝나는 모든 이름은 .txt건너뛰고 나머지는 파일을 cdo info생성하기 위해 처리됩니다( 이것이 실제로 무엇을 하는지 .txt전혀 모릅니다 ). 파일 이름을 먼저 입력할 cdo info필요는 없습니다 . 해당 파일로 리디렉션하면 파일이 생성되기 때문입니다.touch

관련된:


알고 있다면 이름이 다음으로 끝나는 파일만 처리할 것입니다 .nc.

shopt -s dotglob nullglob

for pathname in /filepath/orig/v1/*/*.nc; do
    printf 'Processing "%s"\n' "$pathname" >&2
    cdo info "$pathname" >"$pathname.txt"
done

이름이 다음으로 끝나는 모든 파일을 처리하려는 경우.nc 어딘가에아래에 /filepath/orig/v1:

find /filepath/orig/v1 -type f -name '*.nc' -exec sh -c '
    for pathname do
        printf "Processing \"%s\"\n" "$pathname" >&2
        cdo info "$pathname" >"$pathname.txt"
    done' sh {} +

이렇게 하면 으로 끝나는 발견된 이름이 일괄 처리됩니다 .nc.

하위 디렉터리만 검색 하고 자체 디렉터리는 검색하지 않는 /filepath/orig/v1/*/검색 경로로 사용할 수도 있습니다 .find/filepath/orig/v1/filepath/orig/v1

답변3

개념을 이해하기 어려워서 "찾기"를 포기했는데 이게 효과가 있는 것 같아요~

orig_dir='/filepath/orig/v1'

for entry in "$orig_dir"/*/*; do
    cd "$entry"
    x=`ls *.nc`
    echo "$x"
    name=`basename $x .nc`
    cdo info "$x" > new_path/"$name".txt
    
done

답변4

이 옵션은 GNU 또는 BSD를 사용하는 경우 find사용할 수 있습니다 . 먼저 파일이 포함된 디렉터리로 변경된다는 점을 제외하면 -execdir다른 것과 동일합니다 (종료 대신 -execdir을 사용하면 디렉터리당 분기 양을 최소화하기 위해 동일한 디렉터리에 파일을 일괄 처리합니다). 예를 들어-exec+;

find . -type f -execdir \
  sh -c 'for f; do printf "%s\n" "$f" ; cdo info "$f" > "$f.txt"; done' sh {} +

노트:

  1. for f; do동일합니까?for f in "$@"; do

  2. 이것첫 번째명령의 인수 sh -c '...'는 입니다 . 이는 또는에 의해 실행될 sh프로세스 테이블에서 사용되는 이름입니다 . sh -c원하는 이름이나 -exec-execdir$0shfind-sh일반적으로 사용되는 이름을 사용할 수 있습니다. 존재하지 않는 경우 쉘 스크립트볼 수 없습니다발견된 첫 번째 파일 이름은 find. 이는 sh -c(및 일부 다른 명령, 일반적으로 와 같은 스크립트 해석기 bash -c) 에만 해당 됩니다.아니요사용하거나 실행하려는 대부분의 명령에 find -exec필요합니다 -execdir(즉, 필수 grep가 아님 sed).

  3. 이는 파일이 포함된 디렉토리를 -type f찾고 싶어도 cd디렉토리(또는 소켓, 명명된 파이프, 심볼릭 링크 등)가 아닌 일반 파일만 다루고 싶기 때문입니다. 일반 파일과 심볼릭 링크를 처리하려면 find -L옵션 또는 를 사용하십시오 \( -type f -o -type l \). -L디렉토리에 대한 심볼릭 링크가 따라옵니다.외부일반적으로 원하는 것이 아닌 검색 트리입니다.

    . 을 사용하는 경우 \( -type f -o -type l \)포함된 sh -c스크립트는 각 인수를 확인하여 ( "$f"내 예에서와 같이) 일반 파일인지 또는 일반 파일을 가리키는 심볼릭 링크인지 확인해야 합니다( 에서 언급한 test -f것처럼 help test-hman test 및 제외). -L, 모든 FILE 관련 테스트는 심볼릭 링크를 역참조합니다.").

    find . \( -type f -o -type l \) -execdir \
      sh -c 'for f; do
               printf "%s\n" "$f"
               [ -f "$f" ] && cdo info "$f" > "$f.txt"
             done' sh {} +
    
  4. 스크립트의 모든 변수 확장은 sh -c큰따옴표로 묶입니다. 그래야 하는 대로(참조공백이나 기타 특수 문자 때문에 쉘 스크립트가 멈추는 이유는 무엇입니까?왜)


검색 깊이를 제한해야 하는 경우 이 -maxdepth옵션을 사용할 수 있습니다. 예를 들어

find . -maxdepth 2 -type f -execdir \
  sh -c 'for f; do printf "%s\n" "$f" ; cdo info "$f" > "$f.txt"; done' sh {} +

-dfind에는 또는 등의 관련 옵션도 있고 디렉터리 트리를 탐색하는 방법을 제어할 수도 있습니다 -depth.-mindepth


cdo추신: 이 명령이 수행하는 작업이나 사용되는 인수는 무엇인지 모르지만 --옵션의 끝과 파일 이름 인수의 시작을 표시하는 데 사용을 지원하는 경우 명령에 포함되어야 합니다. 그렇지 않으면 다음 -으로 시작하는 파일 이름이 옵션으로 취급됩니다. 예를 들어 cdo.

find . -type f -execdir \
  sh -c 'for f; do printf "%s\n" "$f" ; cdo info -- "$f" > "$f.txt"; done' sh {} +

printf이것이 내가 대신 사용하는 이유의 일부입니다 echo. 바라보다왜 printf가 echo보다 나은가요?

관련 정보