Unix 쉘 스크립트에서 모든 하위 디렉토리를 탐색하고 무언가를 수행하십시오.


17

쉘 스크립트가 기본 디렉토리의 모든 서브 디렉토리를 방문하기를 원합니다. 디렉토리에서 무언가를하고 출력을 스풀 파일로 보낸 후 다음 디렉토리로 이동하십시오. Main Dir = / tmp Sub Dir = ABCD (4 개의 하위 디렉토리)를 고려하십시오.


2
자, 지금까지 스크립트를 보여주세요. 어느 부분이 문제를 일으키는가?
terdon

답변:


22

for루프를 사용하십시오 :

for d in $(find /path/to/dir -maxdepth 1 -type d)
do
  #Do something, the directory is accessible with $d:
  echo $d
done >output_file

디렉토리의 서브 디렉토리 만 검색합니다 /path/to/dir. 디렉토리 이름에 공백이나 특수 문자가 포함되어 있으면 위의 간단한 예가 실패합니다. 보다 안전한 방법은 다음과 같습니다.

find /tmp -maxdepth 1 -type d -print0 |
  while IFS= read -rd '' dir; do echo "$dir"; done

또는 평범하게 bash:

for d in /path/to/dir/*; do
  if [ -d "$d" ]; then
    echo "$d"
  fi
done

(이와 달리 find디렉토리에 대한 심볼릭 링크를 고려하고 숨겨진 디렉토리는 제외합니다)


1
적어도 그와 find같은 산출물을 처리하는 것과 관련된 한계와 위험을 지적하십시오 .
Stéphane Chazelas

안녕하세요 ... 나는 $ (find / backup / ASHISH -maxdepth 1-타입 d)에서 d에 대해 루프에 대해 아래에서 실행하려고 시도했습니다. ls -l | awk '{print $ 9}'| grep CC * _ date +"%m%d20%Y"| xargs echo echo $ d
Ashish

안녕하세요 ... 아래 루프를 시도했습니다. $ (find / backup / ASHISH -maxdepth 1 -type d)에서 d의 경우 ls -l | awk '{print $ 9}'| grep CC * _ date +"%m%d20%Y"| xargs echo echo $ d 예상 결과는 모든 서브 디렉토리의 ls -ltr입니다. . 위의 루프가 작동하지 않음
Ashish

1

나는 완전한 bash초보자이지만 UN * X 재향 군인입니다. 의심 할 여지없이 Bash 셸 스크립팅에서이 작업을 수행 할 수 있지만 이전에는 find [-maxdepth <levels>] <start-dir> -exec <command> ;이 작업을 수행했습니다. man find누군가가 당신에게 그것을하는 방법을 말할 때까지 당신은 할 수 있고 놀 수 있습니다 bash!


여기에있는 "개요"답변이 투표권을 받았다는 사실에 매우 아첨합니다. 그러나 아래의 @chaos '답변이 다운 투표권을받은 이유는 무엇입니까? (이 게시판에 새로 온 사람으로서 나는이 답변을 자신의 답변에 대해서만 게시 할 수 없으며, 내 의견에 대해서만이 의견을 게시 할 수 없습니다.) 두 번째 제안은 쉘 스크립트 솔루션에 적합하며 외부 find명령 을 실행하는 오버 헤드를 피합니다 .
JonBrave

그의 두 번째는 실제로 맞습니다. 디렉토리 이름에 공백이나 특수 문자 (예 : 백 슬래시)가 있으면 첫 번째는 실패합니다. 안전한 버전에 대한 그의 답변 편집을 참조하십시오.
terdon

나는 동의한다. 내가 칭찬하는 것은 그의 두 번째 쉘 전용 답변이었습니다.
JonBrave 2012

나는 공감대 (내가 던지지 않은)를 설명하고 있었다.
terdon

나는 그것을 캐스팅했다. $(find...)것입니다 나쁜 관행 .
Stéphane Chazelas

1

각 하위 디렉토리 아래에 파일 이름을 원하는 것처럼 보입니다. 는 ls -l | awk그 파일 이름은 공백 및 / 또는 줄 바꿈을 포함하는 어떤 경우에 대한 강력한 충분하지? 아래 find는 그들을 find위해 가지 않는 일에도 -maxdepth적용됩니다.

find . ! -name . -type d -prune -exec sh -c '
   cd "$1" && \
   find "." ! -name . -prune  -type f
' {} {} \;

0

나는 해결책을 얻었다. 아래의 find 명령은 내 요구 사항을 충족합니다.

find . -maxdepth 1 -type d \( ! -name . \) -exec bash -c "cd '{}' && ls -l |awk '{ print $9 }' |grep `date +"%m%d%Y"`|xargs echo" \;

0

ls, grep 및 tr을 사용하는 것도 가능합니다

for dir in $(ls -1FA | grep / | tr -d /); do echo $dir/something; done

ls -1FA | grep / | tr -d / | while IFS= read -r TD; do echo $TD/something; done

ls에 위의 옵션이없는 경우 du / sed를 선택기로 사용할 수도 있습니다.

du --max-depth=1 | sed -e 's/^.*\.\///' | grep -v '\.$'

이 예제는 숨겨진 디렉토리를 리턴하고 상위 및 현재 디렉토리를 제외시키는 것에주의해야합니다.


1
(1) 표준 출력이 파이프 일 때 기본적으로 한 ls줄에 하나의 파일 ( -1옵션이 지정 하는 것 )을  씁니다 (따라서 답이 불필요합니다). (2)의 결과를 파싱 ls하는 것은 나쁜 생각입니다 – 이것이것을보십시오 . 디렉토리에 이름에 공백 (또는 줄 바꿈)이 있으면 첫 번째 대답은 실패하고 이름에 줄 바꿈이 있으면 모두 실패합니다. (3) "$dir"타당한 이유가없는 한 항상 쉘 변수 (예 :)를 인용해야하며 자신이하고있는 일을 확실히 확신해야합니다.
Scott

좋은 지적 스캇. 엄청나게 이름이 붙여진 많은 시스템의 대답을 그대로 남겨두면 여전히 유용 할 수 있다고 생각합니다.
JGurtz
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.