특정 폴더의 모든 하위 디렉토리에서 작업을 수행 해야하는 스크립트를 작성 중입니다.
그것을 작성하는 가장 효율적인 방법은 무엇입니까?
mkdir -p '/tmp/ /etc/passwd /'
위해이 방법에 따라 스크립트를 실행하면 /tmp
삭제 될 수 /etc/passwd
있습니다.
특정 폴더의 모든 하위 디렉토리에서 작업을 수행 해야하는 스크립트를 작성 중입니다.
그것을 작성하는 가장 효율적인 방법은 무엇입니까?
mkdir -p '/tmp/ /etc/passwd /'
위해이 방법에 따라 스크립트를 실행하면 /tmp
삭제 될 수 /etc/passwd
있습니다.
답변:
for D in `find . -type d`
do
//Do whatever you need with D
done
find
재귀 또는 비 재귀 동작을 원하는 경우 매개 변수 를 조정해야합니다 .
find . -mindepth 1 -type d
mkdir 'directory name with spaces'
를 4 개의 개별 단어로 나눕니다.
-mindepth 1 -maxdepth 1
하거나 너무 깊어졌습니다.
하위 프로세스 작성을 피하는 버전 :
for D in *; do
if [ -d "${D}" ]; then
echo "${D}" # your processing here
fi
done
또는 작업이 단일 명령 인 경우 더 간결합니다.
for D in *; do [ -d "${D}" ] && my_command; done
또는 훨씬 더 간결한 버전 ( @enzotib 덕분에 ). 이 버전에서 각 값에는 D
슬래시가 있습니다.
for D in */; do my_command; done
if
또는 [
:와for D in */; do
for D in *; do [ -d "${D}" ] && my_command; done
또는 두 가지 최신 명령 의 조합을 사용하는 것이 좋습니다 .for D in */; do [ -d $D ] && my_command; done
for D in .* *; do
대신 사용하십시오 for D in *; do
.
가장 간단한 비 재귀 방법은 다음과 같습니다.
for d in */; do
echo "$d"
done
/
끝에 만 사용 디렉토리 알려줍니다.
필요가 없습니다
shopt -s dotglob
와일드 카드를 확장 할 때 도트 파일 / dotdir을 포함 하는 데 사용할 수 있습니다 . 또한보십시오 : gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html
/*
대신 */
에 /
사용할 경로를 나타내는.
/*
은 절대 경로를위한 */
것이며 현재 위치의 하위 디렉토리를 포함합니다
${d%/*}
find
명령을 사용하십시오 .GNU에서는 매개 변수 find
를 사용할 수 있습니다 -execdir
.
find . -type d -execdir realpath "{}" ';'
또는 -exec
매개 변수 를 사용하여 :
find . -type d -exec sh -c 'cd -P "$0" && pwd -P' {} \;
또는 다음 xargs
명령으로
find . -type d -print0 | xargs -0 -L1 sh -c 'cd "$0" && pwd && echo Do stuff'
또는 for 루프를 사용하십시오.
for d in */; { echo "$d"; }
재귀의 경우 확장 글러브 ( **/
)를 대신 사용하십시오 (:로 활성화 shopt -s extglob
).
자세한 예 는 각 디렉토리로 이동하여 명령을 실행하는 방법을 참조하십시오. 그래서
-exec {} +
POSIX 지정이고, -exec sh -c 'owd=$PWD; for arg; do cd -- "$arg" && pwd -P; cd -- "$owd"; done' _ {} +
다른 유효한 옵션이며,보다 적은 수의 쉘을 호출합니다 -exec sh -c '...' {} \;
.
편리한 원 라이너
for D in *; do echo "$D"; done
for D in *; do find "$D" -type d; done ### Option A
find * -type d ### Option B
옵션 A는 사이에 공백이있는 폴더에 적합합니다. 또한 폴더 이름의 각 단어를 별도의 엔티티로 인쇄하지 않기 때문에 일반적으로 더 빠릅니다.
# Option A
$ time for D in ./big_dir/*; do find "$D" -type d > /dev/null; done
real 0m0.327s
user 0m0.084s
sys 0m0.236s
# Option B
$ time for D in `find ./big_dir/* -type d`; do echo "$D" > /dev/null; done
real 0m0.787s
user 0m0.484s
sys 0m0.308s
find . -type d -print0 | xargs -0 -n 1 my_command
my_command
입니다.
그러면 서브 쉘이 생성됩니다 (즉, while
루프가 종료 될 때 변수 값이 손실 됨 ).
find . -type d | while read -r dir
do
something
done
이것은하지 않습니다 :
while read -r dir
do
something
done < <(find . -type d)
디렉토리 이름에 공백이 있으면 둘 중 하나가 작동합니다.
find ... -print0
및while IFS="" read -r -d $'\000' dir
-d ''
때문에, bash는 구문과 기능에 대해 오해의 소지가 적은 -d $'\000'
그 (거짓) 의미 $'\000'
에서 몇 가지 방법으로 다른 인 ''
추론에서 (거짓, 다시) 하나가 쉽게 할 수 실제로 - bash는 C 문자열 (NUL 구분, NUL을 포함 할 수 없음) 대신 Pascal 스타일 문자열 (길이 지정, NUL 리터럴 포함 가능)을 지원합니다.
시도해 볼 수 있습니다 :
#!/bin/bash
### $1 == the first args to this script
### usage: script.sh /path/to/dir/
for f in `find . -maxdepth 1 -mindepth 1 -type d`; do
cd "$f"
<your job here>
done
또는 유사한 ...
설명:
find . -maxdepth 1 -mindepth 1 -type d
: 만 1의 1의 최대 재귀 깊이 ($ 1의 하위 디렉토리) 및 최소 깊이 (제외 현재 폴더와 디렉터리를 찾을 수 .
)
cd "$f"
. 의 출력 find
이 문자열 분할 인 경우에는 작동하지 않으므로 에서 이름의 개별 부분을 별도의 값으로 사용하여 확장 확장을 $f
인용하거나 인용하지 않는 정도를 $f
만듭니다.
find
의 출력은 기본 -print
동작 으로 라인 지향적입니다 (이론상 하나의 이름은 한 줄에 있지만 아래 참조) .
find -print
은 임의의 파일 이름을 전달 하는 안전한 방법 이 아닙니다. 파일을 실행 하고 이름에 별도의 행 mkdir -p $'foo\n/etc/passwd\nbar'
이있는 디렉토리를 얻을 수 있기 때문 /etc/passwd
입니다. /upload
또는의 파일에서 이름 처리/tmp
주의하지 않고 디렉토리의 하는 것은 권한 에스컬레이션 공격을 얻는 좋은 방법입니다.
디렉토리 이름에 공백이 있으면 허용되는 대답은 공백으로 구분되며 선호하는 구문은 $()
bash / ksh입니다. 예 GNU find
-exec
를 +;
들어 옵션 사용
find .... -exec mycommand +;
#this is same as passing to xargs
또는 while 루프를 사용하십시오
find .... | while read -r D
do
...
done
find -exec
로 전달하는과 xargs
: find
동안 실행되는 명령의 종료 값을 무시 xargs
제로가 아닌 출구에 실패 할 것입니다. 필요에 따라 정확할 수 있습니다.
find ... -print0 | while IFS= read -r d
더 안전합니다-공백으로 시작하거나 끝나는 이름과 줄 바꿈 문자가 포함 된 이름을 지원합니다.
mkdir 'foo * bar'
하게됩니다foo
와bar
경우에도 이상 반복 할 수 그것들은 존재하지 않으며 모든 파일 이름*
목록 , 디렉토리가 아닌 파일 이름 으로 바뀝니다 ).