如何编写一个bash脚本,该脚本遍历parent_directory中的每个目录,执行 命令 每个目录。
目录结构如下:
parent_directory(名称可以是任何内容 - 不遵循模式)
- 001(目录名称遵循此模式)
- 0001.txt(文件名遵循此模式)
- 0002.txt
- 0003.txt
- 002
- 0001.txt
- 0002.txt
- 0003.txt
- 0004.txt
- 003
- 0001.txt
目录数量未知。
答案 0 :(得分:130)
find . -maxdepth 1 -type d \( ! -name . \) -exec bash -c "cd '{}' && pwd" \;
\( ! -name . \)
避免在当前目录中执行命令。
答案 1 :(得分:91)
当前目录为parent_directory
时,您可以执行以下操作:
for d in [0-9][0-9][0-9]
do
( cd "$d" && your-command-here )
done
(
和)
创建一个子shell,因此主脚本中的当前目录不会更改。
答案 2 :(得分:39)
如果您使用的是GNU find
,则可以尝试-execdir
参数,例如:
find . -type d -execdir realpath "{}" ';'
或(根据@gniourf_gniourf comment):
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建议的那样,在Bash 4.4中可以使用以下方法将find的输出放在数组中而不使用显式循环的唯一正确方法:
mapfile -t -d '' dirs < <(find . -type d -print0)
或不推荐的方式(涉及parsing of ls
):
ls -d */ | awk '{print $NF}' | xargs -n1 sh -c 'cd $0 && pwd && echo Do stuff'
上面的例子会忽略当前的dir(按照OP的要求),但它会破坏带有空格的名字。
另见:
答案 3 :(得分:19)
如果知道toplevel文件夹,你可以写下这样的东西:
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”。
干杯,
答案 4 :(得分:10)
for dir in PARENT/*
do
test -d "$dir" || continue
# Do something with $dir...
done
答案 5 :(得分:8)
您可以通过管道传输然后使用xargs
来实现。要注意的是,您需要使用-I
标志,该标志会将bash命令中的子字符串替换为每个xargs
传递的子字符串。
ls -d */ | xargs -I {} bash -c "cd '{}' && pwd"
您可能想用要在每个目录中执行的任何命令替换pwd
。
答案 6 :(得分:5)
虽然一个衬垫适合快速和脏的使用,但我更喜欢下面更详细的版本来编写脚本。这是我使用的模板,它处理许多边缘情况,并允许您编写更复杂的代码以在文件夹上执行。您可以在函数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"
答案 7 :(得分:4)
你可以使用
find .
搜索当前目录中的所有文件/目录
你可以像这样管道输出xargs命令
find . | xargs 'command here'
答案 8 :(得分:3)
我不明白文件的格式,因为你只想遍历文件夹......你在找这样的东西吗?
cd parent
find . -type d | while read d; do
ls $d/
done
答案 9 :(得分:1)
#!/bin.bash
for folder_to_go in $(find . -mindepth 1 -maxdepth 1 -type d \( -name "*" \) ) ;
# you can add pattern insted of * , here it goes to any folder
#-mindepth / maxdepth 1 means one folder depth
do
cd $folder_to_go
echo $folder_to_go "########################################## "
whatever you want to do is here
cd ../ # if maxdepth/mindepath = 2, cd ../../
done
#you can try adding many internal for loops with many patterns, this will sneak anywhere you want
答案 10 :(得分:0)
for p in [0-9][0-9][0-9];do
(
cd $p
for f in [0-9][0-9][0-9][0-9]*.txt;do
ls $f; # Your operands
done
)
done