如何在所有可能的子目录中执行bash命令?

如何在所有可能的子目录中执行bash命令?

假设我的主目录是/home/test

在它下面我有很多子目录,子目录下还有很多子目录,依此类推。

例子:

/home/test
/home/test/subdir1
/home/test/subdir1/subdir2
/home/test/subdir1/subdir2/subdir3
/home/test/subdir1/subdir2/subdir4
/home/test/subdir1/subdir2/subdir4/subdir5

等等 ...

我想要一个简单的脚本,它接受每个目录并只运行命令pwd

答案1

使用并行的解决方案

您可以使用 GNU Parallel 来获得紧凑、更快的解决方案。

find . -type d -print0 | parallel -0 cd {}'&&' <command-name>

即使对于包含空格和换行符的目录名,这也绝对可以正常工作。这里的作用parallel是,它从 中获取输出find,这是每个目录,然后使用 将其提供给 cd {}。然后,如果更改目录成功,则会在此目录下运行单独的命令。

使用 while 循环的常规解决方案

find "$PWD" -type d | while read -r line; do cd "$line" && <command-name>; done;

请注意,$PWD此处使用的是因为该变量包含绝对路径运行命令的当前目录。如果不使用绝对路径,则cd可能会在 while 循环中抛出错误。

这是一个更简单的解决方案。它在大多数情况下都可以工作,除非目录名称中包含奇怪的字符(例如换行符)(请参阅注释)。

答案2

find命令功能强大,但使用起来有点困难。
我很确定它可以满足您的需要 - 下面的命令“几乎”是您所要求的:

find . -type d -execdir pwd \;

但是 - 这不会在最深的目录级别运行该命令 - 它会在找到其他目录的目录中运行。

所以它会运行进去subdir4,因为它包含subdir5.但不是subdir5——正如你可能期望的那样。

重要的是-execdir使用该选项,而不是更知名的选项-exec(请参阅 参考资料man find):

-exec选项在启动目录中运行命令,并且还有其他缺点:

    -exec command ;
           Execute command; true if 0 status  is  returned.   All  following
           arguments  to find are taken to be arguments to the command until
           an argument consisting of ';' is encountered.  The string '{}' is
           replaced  by  the current file name being processed everywhere it
           occurs in the arguments to the command,  not  just  in  arguments
           where  it  is  alone, as in some versions of find.  Both of these
           constructions might need to be escaped (with a \ ) or quoted  to
           protect  them from expansion by the shell.  See the EXAMPLES sec‐
           tion for examples of the use of the -exec option.  The  specified
           command  is  run once for each matched file.  The command is exe‐
           cuted in the starting directory.   There are unavoidable security
           problems  surrounding use of the -exec action; you should use the
          -execdir option instead.

但该选项-execdir正是您所要求的:

   -execdir command ;
   -execdir command {} +
           Like  -exec,  but the specified command is run from the subdirec‐
           tory containing the matched  file,  which  is  not  normally  the
           directory  in  which  you  started find.  This a much more secure
           method for invoking commands, as it avoids race conditions during
           resolution  of the paths to the matched files.  As with the -exec
           action, the '+' form of -execdir will build  a  command  line  to
           process  more  than one matched file, but any given invocation of
           command will only list files that exist in the same subdirectory.
           If  you use this option, you must ensure that your $PATH environ‐
           ment variable does not reference '.'; otherwise, an attacker  can
           run any commands they like by leaving an appropriately-named file
           in a directory in which you will run -execdir.  The same  applies
           to having entries in $PATH which are empty or which are not abso‐
           lute directory names.

答案3

其他答案之一与此接近:

寻找 。 -type d -exec sh -c 'cd "$0" &&指令' {} \;

(仅当cd成功时才运行该命令)。有些人建议插入一个虚拟参数,这样找到的目录 ( {}) 就会滑到$1

寻找 。 -type d -exec sh -c 'cd "$1" &&指令' foo {} ";"

当然,您可以在此处使用任何字符串来代替foo。常见的选择包括---、 和sh。该字符串将用于错误消息(如果有),例如,

foo: 第 0 行: cd:受限目录: 没有权限

所以sh似乎是一个不错的选择。  \;";"是绝对等价的;这只是一种风格偏好。

上述命令为每个目录执行一次 shell。这可能会带来一些性能损失(特别是如果要执行的命令相对较轻)。替代方案包括

寻找 。 -type d -exec sh -c 'for d;做(cd“$d”&&指令);完成' sh {} +

它执行 shell 一次,但为每个目录分叉一次,并且

寻找 。 -type d -exec sh -c 'save_d=$PWD;对于 d;执行 cd "$d" &&指令; cd“$save_d”;完成' sh {} +

它不会产生任何子壳。如果您正在搜索绝对路径,正如您的问题所示,您可以结合上述内容并执行

查找 /home/test -type d -exec sh -c 'for d;执行 cd "$d" &&指令;完成' sh {} +

它不会产生任何子 shell,也不必费心保存起点。

答案4

你可以使用这样的东西

find /home/test/ -type d -exec bash -c '<Command to be executed>' \; 

例子:

以下命令将显示目录名,类似于运行 pwd 命令。

find /home/test/ -type d -exec bash -c 'echo $0' \;

相关内容