[bash] 각 디렉토리로 이동하여 명령을 실행하는 방법은 무엇입니까?
어떻게 parent_directory 내에서 각 디렉토리를 통과하고 bash는 스크립트 작성합니까 실행 명령 에 각 디렉토리를 .
디렉토리 구조는 다음과 같습니다.
parent_directory (이름은 무엇이든 될 수 있습니다-패턴을 따르지 않습니다)
- 001 (디렉토리 이름은이 패턴을 따릅니다)
- 0001.txt (파일 이름은이 패턴을 따릅니다)
- 0002.txt
- 0003.txt
- 002
- 0001.txt
- 0002.txt
- 0003.txt
- 0004.txt
- 003
- 0001.txt
디렉토리 수를 알 수 없습니다.
답변
현재 디렉토리가 다음과 같은 경우 다음을 수행 할 수 있습니다 parent_directory
.
for d in [0-9][0-9][0-9]
do
( cd "$d" && your-command-here )
done
(
하고 )
현재 디렉토리가 기본 스크립트에서 변경되지 않도록, 서브 쉘을 만들 수 있습니다.
답변
find . -maxdepth 1 -type d \( ! -name . \) -exec bash -c "cd '{}' && pwd" \;
\( ! -name . \)
현재 디렉토리에서 명령을 실행 피한다.
답변
GNU를 사용하는 경우 다음 과 같은 매개 변수 find
를 사용해 볼 수 있습니다 -execdir
.
find . -type d -execdir realpath "{}" ';'
또는 ( @gniourf_gniourf 주석에 따라 ) :
find . -type d -execdir sh -c 'printf "%s/%s\n" "$PWD" "$0"' {} \;
참고 : 전면 을 수정 하는 ${0#./}
대신 사용할 수 있습니다 .$0
./
또는 더 실용적인 예 :
find . -name .git -type d -execdir git pull -v ';'
현재 디렉토리를 포함하려면 다음을 사용하여 훨씬 간단합니다 -exec
.
find . -type d -exec sh -c 'cd -P -- "{}" && pwd -P' \;
또는 사용 xargs
:
find . -type d -print0 | xargs -0 -L1 sh -c 'cd "$0" && pwd && echo Do stuff'
또는 @gniourf_gniourf가 제안한 비슷한 예 :
find . -type d -print0 | while IFS= read -r -d '' file; do
# ...
done
위의 예제는 이름에 공백이있는 디렉토리를 지원합니다.
또는 bash 배열에 할당하여 :
dirs=($(find . -type d))
for dir in "${dirs[@]}"; do
cd "$dir"
echo $PWD
done
.
특정 폴더 이름으로 변경하십시오 . 재귀 적으로 실행할 필요가 없으면 dirs=(*)
대신 다음을 사용할 수 있습니다 . 위의 예는 이름에 공백이있는 디렉토리를 지원하지 않습니다.
@gniourf_gniourf가 제안한 것처럼 명시 적 루프를 사용하지 않고 배열에 find 출력을 넣는 유일한 방법은 Bash 4.4에서 다음과 같이 사용할 수 있습니다.
mapfile -t -d '' dirs < <(find . -type d -print0)
또는 권장되지 않는 방법 ( 파싱ls
포함 ) :
ls -d */ | awk '{print $NF}' | xargs -n1 sh -c 'cd $0 && pwd && echo Do stuff'
위의 예는 현재 dir을 무시하지만 (OP에서 요청한대로) 공백이있는 이름을 구분합니다.
또한보십시오:
- 배쉬 : SO의 각 디렉토리
- 현재 경로에 모든 디렉토리를 입력하고 스크립트를 실행하는 방법은 무엇입니까? SE 우분투에서
답변
파이핑 한 다음을 사용하여이 작업을 수행 할 수 있습니다 xargs
. catch는 -I
bash 명령의 하위 문자열을 각각이 전달한 하위 문자열로 대체 하는 플래그 를 사용해야 합니다 xargs
.
ls -d */ | xargs -I {} bash -c "cd '{}' && pwd"
pwd
각 디렉토리에서 실행하려는 명령 으로 바꿀 수 있습니다 .
답변
최상위 폴더가 알려진 경우 다음과 같이 작성할 수 있습니다.
for dir in `ls $YOUR_TOP_LEVEL_FOLDER`;
do
for subdir in `ls $YOUR_TOP_LEVEL_FOLDER/$dir`;
do
$(PLAY AS MUCH AS YOU WANT);
done
done
$ (원하는대로 플레이); 원하는만큼 코드를 넣을 수 있습니다.
나는 어떤 디렉토리에서도 “cd”를하지 않았다.
건배,
답변
for dir in PARENT/*
do
test -d "$dir" || continue
# Do something with $dir...
done
답변
하나의 라이너는 빠르고 더러운 사용법에 좋지만 스크립트 작성에 더 자세한 버전을 선호합니다. 이것은 내가 사용하는 템플릿으로 많은 경우를 처리하며 폴더에서 실행할 더 복잡한 코드를 작성할 수 있습니다. dir_command 함수에서 bash 코드를 작성할 수 있습니다. 아래에서 dir_coomand는 예제로 git의 각 저장소에 태그를 지정합니다. 나머지 스크립트는 디렉토리의 각 폴더에 대해 dir_command를 호출합니다. 주어진 폴더 세트 만 반복하는 예제도 포함됩니다.
#!/bin/bash
#Use set -x if you want to echo each command while getting executed
#set -x
#Save current directory so we can restore it later
cur=$PWD
#Save command line arguments so functions can access it
args=("$@")
#Put your code in this function
#To access command line arguments use syntax ${args[1]} etc
function dir_command {
#This example command implements doing git status for folder
cd $1
echo "$(tput setaf 2)$1$(tput sgr 0)"
git tag -a ${args[0]} -m "${args[1]}"
git push --tags
cd ..
}
#This loop will go to each immediate child and execute dir_command
find . -maxdepth 1 -type d \( ! -name . \) | while read dir; do
dir_command "$dir/"
done
#This example loop only loops through give set of folders
declare -a dirs=("dir1" "dir2" "dir3")
for dir in "${dirs[@]}"; do
dir_command "$dir/"
done
#Restore the folder
cd "$cur"