폴더를 반복하여 파일을 가져오고 해당 파일에 대한 작업을 수행하여 파일과 이름이 같은 텍스트 파일로 출력을 리디렉션하려고 합니다. 나는 "찾기"를 사용해 보았습니다 -
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 {} +
노트:
for f; do
동일합니까?for f in "$@"; do
이것첫 번째명령의 인수
sh -c '...'
는 입니다 . 이는 또는에 의해 실행될sh
프로세스 테이블에서 사용되는 이름입니다 .sh -c
원하는 이름이나-exec
-execdir
$0
sh
find-sh
일반적으로 사용되는 이름을 사용할 수 있습니다. 존재하지 않는 경우 쉘 스크립트볼 수 없습니다발견된 첫 번째 파일 이름은find
. 이는sh -c
(및 일부 다른 명령, 일반적으로 와 같은 스크립트 해석기bash -c
) 에만 해당 됩니다.아니요사용하거나 실행하려는 대부분의 명령에find -exec
필요합니다-execdir
(즉, 필수grep
가 아님sed
).이는 파일이 포함된 디렉토리를
-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 {} +
스크립트의 모든 변수 확장은
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 {} +
-d
find에는 또는 등의 관련 옵션도 있고 디렉터리 트리를 탐색하는 방법을 제어할 수도 있습니다 -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보다 나은가요?