bash 如何进入每个目录并执行命令?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7470165/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to go to each directory and execute a command?
提问by Van de Graff
How do I write a bash script that goes through each directory inside a parent_directory and executesa commandin each directory.
如何编写一个 bash 脚本,它遍历 parent_directory中的每个目录并在每个目录中执行一个命令。
The directory structure is as follows:
目录结构如下:
parent_directory (name could be anything - doesnt follow a pattern)
- 001 (directory names follow this pattern)
- 0001.txt (filenames follow this pattern)
- 0002.txt
- 0003.txt
- 002
- 0001.txt
- 0002.txt
- 0003.txt
- 0004.txt
- 003
- 0001.txt
the number of directories is unknown.
parent_directory(名称可以是任何东西 - 不遵循模式)
- 001(目录名称遵循此模式)
- 0001.txt(文件名遵循此模式)
- 0002.txt
- 0003.txt
- 002
- 0001.txt
- 0002.txt
- 0003.txt
- 0004.txt
- 003
- 0001.txt
目录数量未知。
采纳答案by Mark Longair
You can do the following, when your current directory is parent_directory
:
当您的当前目录为 时,您可以执行以下操作parent_directory
:
for d in [0-9][0-9][0-9]
do
( cd "$d" && your-command-here )
done
The (
and )
create a subshell, so the current directory isn't changed in the main script.
该(
和)
创建一个子shell,所以当前目录没有在主脚本改变。
回答by Christian Vielma
回答by kenorb
If you're using GNU find
, you can try -execdir
parameter, e.g.:
如果您使用的是 GNU find
,则可以尝试-execdir
参数,例如:
find . -type d -execdir realpath "{}" ';'
or (as per @gniourf_gniourf comment):
或(根据@gniourf_gniourf 评论):
find . -type d -execdir sh -c 'printf "%s/%s\n" "$PWD" "find . -name .git -type d -execdir git pull -v ';'
"' {} \;
Note: You can use ${0#./}
instead of $0
to fix ./
in the front.
注意:您可以使用${0#./}
代替$0
来固定./
在前面。
or more practical example:
或更实际的例子:
find . -type d -exec sh -c 'cd -P -- "{}" && pwd -P' \;
If you want to include the current directory, it's even simpler by using -exec
:
如果要包含当前目录,使用-exec
以下命令会更简单:
find . -type d -print0 | xargs -0 -L1 sh -c 'cd "find . -type d -print0 | while IFS= read -r -d '' file; do
# ...
done
" && pwd && echo Do stuff'
or using xargs
:
或使用xargs
:
dirs=($(find . -type d))
for dir in "${dirs[@]}"; do
cd "$dir"
echo $PWD
done
Or similar example suggested by @gniourf_gniourf:
或@gniourf_gniourf建议的类似示例:
mapfile -t -d '' dirs < <(find . -type d -print0)
The above examples support directories with spaces in their name.
上面的示例支持名称中带有空格的目录。
Or by assigning into bash array:
或者通过分配到 bash 数组:
ls -d */ | awk '{print $NF}' | xargs -n1 sh -c 'cd ls -d */ | xargs -I {} bash -c "cd '{}' && pwd"
&& pwd && echo Do stuff'
Change .
to your specific folder name. If you don't need to run recursively, you can use: dirs=(*)
instead. The above example doesn't support directories with spaces in the name.
更改.
为您的特定文件夹名称。如果您不需要递归运行,则可以使用:dirs=(*)
代替。上面的示例不支持名称中带有空格的目录。
So as @gniourf_gniourfsuggested, the only proper way to put the output of find in an array without using an explicit loop will be available in Bash 4.4 with:
因此,正如@gniourf_gniourf 所建议的那样,将 find 的输出放入数组而不使用显式循环的唯一正确方法将在 Bash 4.4 中提供:
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
Or not a recommended way (which involves parsing of ls
):
或者不是推荐的方式(包括解析ls
):
for dir in PARENT/*
do
test -d "$dir" || continue
# Do something with $dir...
done
The above example would ignore the current dir (as requested by OP), but it'll break on names with the spaces.
上面的示例将忽略当前目录(根据 OP 的要求),但它会破坏带有空格的名称。
See also:
也可以看看:
- Bash: for each directoryat SO
- How to enter every directory in current path and execute script?at SE Ubuntu
- Bash:对于SO 处的每个目录
- 如何进入当前路径中的每个目录并执行脚本?在 SE Ubuntu
回答by Piyush Singh
You can achieve this by piping and then using xargs
. The catch is you need to use the -I
flag which will replace the substring in your bash command with the substring passed by each of the xargs
.
您可以通过管道然后使用xargs
. 问题是您需要使用-I
标志,它将用每个 .bashrc 文件传递的子字符串替换 bash 命令中的子字符串xargs
。
#!/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
echo "$(tput setaf 2)$(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"
You may want to replace pwd
with whatever command you want to execute in each directory.
您可能希望替换pwd
为您想在每个目录中执行的任何命令。
回答by gforcada
If the toplevel folder is known you can just write something like this:
如果顶层文件夹是已知的,你可以这样写:
cd parent
find . -type d |?while read d; do
ls $d/
done
On the $(PLAY AS MUCH AS YOU WANT); you can put as much code as you want.
在 $(随心所欲地玩);您可以根据需要放置尽可能多的代码。
Note that I didn't "cd" on any directory.
请注意,我没有在任何目录上“cd”。
Cheers,
干杯,
回答by Idelic
find .
回答by Shital Shah
While one liners are good for quick and dirty usage, I prefer below more verbose version for writing scripts. This is the template I use which takes care of many edge cases and allows you to write more complex code to execute on a folder. You can write your bash code in the function dir_command. Below, dir_coomand implements tagging each repository in git as an example. Rest of the script calls dir_command for each folder in directory. The example of iterating through only given set of folder is also include.
虽然一个衬垫适合快速和肮脏的使用,但我更喜欢下面更详细的版本来编写脚本。这是我使用的模板,它处理许多边缘情况,并允许您编写更复杂的代码以在文件夹上执行。您可以在函数 dir_command 中编写 bash 代码。下面以dir_coomand在git中实现给每个仓库打标签为例。脚本的其余部分为目录中的每个文件夹调用 dir_command。还包括仅迭代给定文件夹集的示例。
find . | xargs 'command here'
回答by Aif
I don't get the point with the formating of the file, since you only want to iterate through folders... Are you looking for something like this?
我不明白文件的格式,因为你只想遍历文件夹......你在寻找这样的东西吗?
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
回答by Dan Bizdadea
you can use
您可以使用
##代码##to search all files/dirs in the current directory recurive
搜索当前目录中的所有文件/目录递归
Than you can pipe the output the xargs command like so
比你可以像这样输出 xargs 命令
##代码##