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

you*_*ek1 8 shell directory directory-structure files

假设我的主目录是 /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
Run Code Online (Sandbox Code Playgroud)

等等 ...

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

shi*_*ams 8

使用并行的解决方案

您可以将 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 循环中引发错误。

这是一个更简单的解决方案。它在大多数情况下都可以工作,除非目录名称中有像换行符这样的奇怪字符(见评论)。

  • GNU Parallel 有 -0 和 --null。OP 写道 _he_ 有子目录。所以它很可能不是恶意用户。我还没有看到由非恶意用户创建的带有 \n 的目录名称。空间,是的。报价,是的。星形、波浪形和管道,是的。但从来没有\n。 (2认同)

Vol*_*gel 5

find命令功能强大,但这使得使用起来有点挑战。
我很确定它可以做你需要的 - 下面的这个命令“几乎”是你要求的:

find . -type d -execdir pwd \;
Run Code Online (Sandbox Code Playgroud)

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

所以它会运行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.
Run Code Online (Sandbox Code Playgroud)

但该选项-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.
Run Code Online (Sandbox Code Playgroud)

  • 嗯...这将在具有多个子目录的同一目录上多次运行相同的命令(例如,如果 `dir1` 下面一级有 100 个目录,它将执行 `execdir pwd` 100 次)。 (2认同)

Per*_*ulf 0

您不需要运行额外的pwd 命令,您可以运行以下命令:

find test/ -type d
Run Code Online (Sandbox Code Playgroud)

您可以将您的目录替换为test/