리눅스에서 디렉토리를 반복하는 방법?


168

Linux에서 bash로 스크립트를 작성 중이며 주어진 디렉토리의 모든 하위 디렉토리 이름을 거쳐야합니다. 이 디렉토리를 반복하고 정규 파일을 건너 뛰려면 어떻게해야합니까?

예를 들어
, 주어진 디렉토리는 /tmp/
다음과 같은 서브 디렉토리를 갖습니다./tmp/A, /tmp/B, /tmp/C

A, B, C를 검색하고 싶습니다.


답변:


129
cd /tmp
find . -maxdepth 1 -mindepth 1 -type d -printf '%f\n'

간단한 설명 :

  • find 파일을 찾습니다 (분명히)

  • .is 다음에있는 현재 디렉토리 cd입니다 /tmp(IMHO /tmpfind명령에 직접 사용하는 것보다 융통성이 있습니다 . cd이 폴더에서 추가 조치를 수행하려는 경우 변경할 위치가 하나뿐입니다 ).

  • -maxdepth 1하고 -mindepth 1있는지 확인 find은 현재 디렉토리에있는 외모와 포함하지 않는 .결과 자체를

  • -type d 디렉토리 만 찾습니다

  • -printf '%f\n 각 적중에 대해 찾은 폴더 이름 (및 줄 바꾸기) 만 인쇄합니다.

vo!


그건 그렇고 : 모든 대답에는 숨겨진 폴더도 발견됩니다 (즉, 점으로 시작하는 폴더)! 이것을 원하지 않으면 printf 또는 exec 옵션 앞에`-regex '\ ./ [^ \.]. *'를 추가하십시오.
Boldewyn

1
도움이됩니다 — 각 적중마다 하나의 명령 만 실행해야하는 경우 ;-) — 실행할 명령이 몇 개뿐입니다.
Martin

문제 없음 :이 솔루션을 채택하십시오 : transnum.blogspot.de/2008/11/…while..done 루프 안에서 당신은 미쳐 갈 수 있습니다.
Boldewyn

1
이것은 일부 유스 케이스에 매우 좋은 방법입니다. find-exec옵션을 사용하면 각 파일 / 디렉토리에 대한 모든 명령을 실행할 수 있습니다.
jtpereyda

451

지금까지의 모든 대답은을 사용 find하므로 쉘 만있는 답변이 있습니다 . 귀하의 경우 외부 도구가 필요하지 않습니다.

for dir in /tmp/*/     # list directories in the form "/tmp/dirname/"
do
    dir=${dir%*/}      # remove the trailing "/"
    echo ${dir##*/}    # print everything after the final "/"
done

18
+ find
1-

19
for dir in */; do echo $dir; done현재 디렉토리의 디렉토리도 마찬가지 입니다.
Ehtesh Choudhury

41
그것이 무엇을 dir=${dir%*/}하고 있는지 설명을 포함 할 수 있다면 좋을 echo ${dir##*/}것입니다.
Jeremy S.

11
변수 dir은 끝에 백 슬래시를 포함하기 때문입니다. 그는 단지 이름을 깨끗하게하기 위해 그것을 제거하고 있습니다. %는 끝에 /를 제거합니다. ##은 처음에 /를 제거합니다. 하위 문자열을 처리하는 연산자입니다.
sfratini

8
일치하는 것이 없으면 루프가로 트리거되며 /tmp/*/디렉토리가 실제로 존재하는지 확인하는 것이 좋습니다.
Jrs42

41

숨겨진 디렉토리 (점으로 시작)를 포함한 모든 디렉토리를 다음과 같이 반복 할 수 있습니다.

for file in */ .*/ ; do echo "$file is a directory"; done

참고 : 폴더에 숨겨진 디렉토리가 하나 이상있는 경우에만 목록 사용이 */ .*/zsh에서 작동합니다. 배쉬에서는 또한 표시됩니다 ...


bash가 숨겨진 디렉토리를 포함하는 또 다른 가능성은 다음을 사용하는 것입니다.

shopt -s dotglob;
for file in */ ; do echo "$file is a directory"; done

심볼릭 링크를 제외하려면 다음을 수행하십시오.

for file in */ ; do 
  if [[ -d "$file" && ! -L "$file" ]]; then
    echo "$file is a directory"; 
  fi; 
done

각 솔루션에서 후행 디렉토리 이름 (질문에 따라 A, B, C) 만 출력하려면 루프 내에서 이것을 사용하십시오.

file="${file%/}"     # strip trailing slash
file="${file##*/}"   # strip path and leading slash
echo "$file is the directoryname without slashes"

예 (공백이 포함 된 디렉토리에서도 작동) :

mkdir /tmp/A /tmp/B /tmp/C "/tmp/ dir with spaces"
for file in /tmp/*/ ; do file="${file%/}"; echo "${file##*/}"; done

16

공백이 포함 된 디렉토리에서 작동

Sorpigal에서 영감을 받음

while IFS= read -d $'\0' -r file ; do 
    echo $file; ls $file ; 
done < <(find /path/to/dir/ -mindepth 1 -maxdepth 1 -type d -print0)

원본 게시물 (공백과 함께 작동하지 않음)

Boldewyn에서 영감을 얻음 : find명령 이있는 루프의 예 .

for D in $(find /path/to/dir/ -mindepth 1 -maxdepth 1 -type d) ; do
    echo $D ;
done


6

내가 가장 자주 사용하는 기술은 find | xargs입니다. 예를 들어,이 디렉토리의 모든 파일과 모든 서브 디렉토리를 모두 읽을 수있게하려면 다음을 수행하십시오.

find . -type f -print0 | xargs -0 chmod go+r
find . -type d -print0 | xargs -0 chmod go+rx

-print0옵션은 공백 대신 NULL 문자로 종료됩니다. 이 -0옵션은 입력을 같은 방식으로 나눕니다. 공백이있는 파일에 사용하는 조합입니다.

이 명령 체인을 모든 라인 출력을 가져 와서 명령 find끝에 붙여서 그림으로 표시 할 수 있습니다 chmod.

명령이 끝이 아닌 중간에 인수로 실행하려면 약간 창의적이어야합니다. 예를 들어, 모든 하위 디렉토리로 변경하고 명령을 실행해야했습니다 latemk -c. 그래서 나는 ( Wikipedia에서 ) 사용했다 :

find . -type d -depth 1 -print0 | \
    xargs -0 sh -c 'for dir; do pushd "$dir" && latexmk -c && popd; done' fnord

이 효과는 for dir $(subdirs); do stuff; done있지만 이름에 공백이있는 디렉토리에는 안전합니다. 또한 별도의 호출 stuff이 동일한 쉘에서 이루어 지므로 내 명령에서을 사용하여 현재 디렉토리로 돌아 가야합니다 popd.


3

빌드 할 수있는 최소 bash 루프 (ghostdog74 답변 기반)

for dir in directory/*                                                     
do                                                                                 
  echo ${dir}                                                                  
done

디렉토리별로 전체 파일을 압축

for dir in directory/*
do
  zip -r ${dir##*/} ${dir}
done                                               

directory하위 디렉토리뿐만 아니라 의 모든 파일이 나열 됩니다.
dexteritas

2

find . -type d -maxdepth 1


2
이 답변은 전체 경로를받는 반면 디렉토리의 이름 만 원한다는 것을 제외하고는 좋습니다.
Erik Sapir

2

당신이 for 루프에서 여러 명령을 실행할 경우의 결과를 저장할 수 findmapfile변수로 (bash는> = 4)과 함께 배열을 통해 이동합니다 ${dirlist[@]}. 공백이 포함 된 디렉토리에서도 작동합니다.

find명령은 Boldewyn 의 답변 을 기반으로합니다 . find명령 에 대한 자세한 정보는 여기에서 찾을 수 있습니다.

IFS=""
mapfile -t dirlist < <( find . -maxdepth 1 -mindepth 1 -type d -printf '%f\n' )
for dir in ${dirlist[@]}; do
    echo ">${dir}<"
    # more commands can go here ...
done
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.