如何进入每个目录并执行命令?

Van*_*aff 131 unix bash shell find

我怎样写一个bash脚本,通过每一个目录使用一个parent_directory内执行一个命令每个目录.

目录结构如下:

parent_directory(名称可以是任何内容 - 不遵循模式)

  • 001(目录名称遵循此模式)
    • 0001.txt(文件名遵循此模式)
    • 0002.txt
    • 0003.txt
  • 002
    • 0001.txt
    • 0002.txt
    • 0003.txt
    • 0004.txt
  • 003
    • 0001.txt

目录数量未知.

Chr*_*lma 143

这个答案张贴由托德帮我.

find . -maxdepth 1 -type d \( ! -name . \) -exec bash -c "cd '{}' && pwd" \;
Run Code Online (Sandbox Code Playgroud)

\( ! -name . \) 当前目录下执行命令避免.

  • 您还可以通过添加`-mindepth 1`来省略当前目录 (10认同)
  • 如果你只想在某些文件夹中运行命令:`find FOLDER*-maxdepth 0 -type d \(!-name.\)-exec bash -c"cd'{}'&& pwd"\;` (4认同)
  • 我不得不做`-exec bash -c'cd"$ 0"&& pwd'{} \;`因为一些目录包含单引号和一些双引号. (3认同)

Mar*_*air 101

当前目录为parent_directory:时,您可以执行以下操作:

for d in [0-9][0-9][0-9]
do
    ( cd "$d" && your-command-here )
done
Run Code Online (Sandbox Code Playgroud)

()创建一个子shell,所以当前目录没有在主脚本改变.

  • 这里没关系,因为通配符与数字不匹配,但在一般情况下,您基本上总是希望将目录名称放在循环内的双引号中.`cd"$ d"`会更好,因为它转移到通配符匹配其名称包含空格和/或shell元字符的文件的情况. (4认同)

ken*_*orb 41

如果您使用的是GNU find,可以尝试-execdir参数,例如:

find . -type d -execdir realpath "{}" ';'
Run Code Online (Sandbox Code Playgroud)

或(根据@gniourf_gniourf评论):

find . -type d -execdir sh -c 'printf "%s/%s\n" "$PWD" "$0"' {} \;
Run Code Online (Sandbox Code Playgroud)

注意:您可以使用${0#./}而不是在前面$0修复./.

或更实际的例子:

find . -name .git -type d -execdir git pull -v ';'
Run Code Online (Sandbox Code Playgroud)

如果要包含当前目录,则使用-exec以下内容更简单:

find . -type d -exec sh -c 'cd -P -- "{}" && pwd -P' \;
Run Code Online (Sandbox Code Playgroud)

或使用xargs:

find . -type d -print0 | xargs -0 -L1 sh -c 'cd "$0" && pwd && echo Do stuff'
Run Code Online (Sandbox Code Playgroud)

@gniourf_gniourf建议的类似示例:

find . -type d -print0 | while IFS= read -r -d '' file; do
# ...
done
Run Code Online (Sandbox Code Playgroud)

上面的示例支持名称中包含空格的目录.


或者通过分配到bash数组:

dirs=($(find . -type d))
for dir in "${dirs[@]}"; do
  cd "$dir"
  echo $PWD
done
Run Code Online (Sandbox Code Playgroud)

更改.为您的特定文件夹名称.如果您不需要递归运行,则可以使用:dirs=(*)代替.上面的示例不支持名称中包含空格的目录.

因此,正如@gniourf_gniourf建议的那样,在不使用显式循环的情况下将find的输出放在数组中的唯一正确方法将在Bash 4.4中提供:

mapfile -t -d '' dirs < <(find . -type d -print0)
Run Code Online (Sandbox Code Playgroud)

或者不推荐的方式(涉及解析ls):

ls -d */ | awk '{print $NF}' | xargs -n1 sh -c 'cd $0 && pwd && echo Do stuff'
Run Code Online (Sandbox Code Playgroud)

上面的例子会忽略当前的dir(按照OP的要求),但它会打破带有空格的名字.

也可以看看:


gfo*_*ada 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
Run Code Online (Sandbox Code Playgroud)

在$(尽可能多玩); 你可以根据需要添加尽可能多的代码.

请注意,我没有在任何目录上"cd".

干杯,

  • 这里有几个["无用的使用`ls`"](http://partmaps.org/era/unix/award.html#ls) - 您可以在$ YOUR_TOP_LEVEL_FOLDER/*中执行`for dir `而不是. (3认同)

Piy*_*ngh 18

您可以通过配管,然后使用来实现此目的xargs。要注意的是,您需要使用-I标志,该标志将bash命令中的子字符串替换为每个传递的子字符串xargs

ls -d */ | xargs -I {} bash -c "cd '{}' && pwd"
Run Code Online (Sandbox Code Playgroud)

您可能要替换pwd为要在每个目录中执行的任何命令。

  • 我不知道为什么这还没有被赞成,但是我找到了迄今为​​止最简单的脚本。谢谢 (2认同)

Ide*_*lic 10

for dir in PARENT/*
do
  test -d "$dir" || continue
  # Do something with $dir...
done
Run Code Online (Sandbox Code Playgroud)

  • 这很容易理解! (2认同)

Shi*_*hah 6

虽然一个衬垫适合快速和脏的使用,我更喜欢下面更详细的版本来编写脚本.这是我使用的模板,它处理许多边缘情况,并允许您编写更复杂的代码以在文件夹上执行.您可以在函数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"
Run Code Online (Sandbox Code Playgroud)


Aif*_*Aif 5

我不明白文件的格式,因为你只想遍历文件夹......你在寻找这样的东西吗?

cd parent
find . -type d | while read d; do
   ls $d/
done
Run Code Online (Sandbox Code Playgroud)