cd进入所有目录,对该目录中的文件执行命令,然后返回到先前的当前目录


41

我正在尝试编写一个脚本,该脚本将在具有许多单级子目录的给定目录中运行。该脚本将CD进入每个子目录,对目录中的文件执行命令,然后CD出继续进入下一个目录。做这个的最好方式是什么?


1
鉴于当前提供的信息水平,我认为与无关youtube-dl
HalosGhost 2014年

Answers:


83
for d in ./*/ ; do (cd "$d" && somecommand); done

12
因此,由于答复者已省略了任何解释,因此我将尝试其中的一种。for d in ./*/启动一个循环,该循环将每个项目./*/(在这种情况下为文件/文件夹列表)存储在变量中$ddo (cd "$d" && somecommand);开始循环的主体。在主体内部,它启动子壳并运行cdsomecommand命令。由于它是子外壳程序,因此父外壳程序(从中运行此命令的外壳程序)保留其CWD和其他环境变量。done只需闭合回路主体即可。
Qix 2014年

此方法适用于目录的子目录: for d in ./*/ ; do (cd "$d" && ls); done,将不起作用。但是,for d in ./*/ ; do (cd "$d" && for d in ./*/ ; do (cd "$d" && ls); done ); done会工作。-在本例中使用ls作为命令。
Michael Dimmitt

-bash: cd: ./*/: No such file or directory
S.TarıkÇetin

15

最好的方法是完全不使用cd

find some/dir -type f -execdir somecommand {} \;

execdir就像exec,但是工作目录不同:

   -execdir command {} [;|+]
          Like   -exec,   but  the  specified  command  is  run  from  the
          subdirectory 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.

不是POSIX。


这对别名有用吗?我可以下载某些文件,但是当我键入find * /。link -type f -execdir md $(cat .link){} \时,它无法识别。
琼斯的事

@SomethingJones否,find执行这些命令,因此不会知道别名。什么是md和是.link一个目录?
muru 2014年

.link是一个文本文件,其中包含需要下载的URL。md是wget的别名,带有一组标志。有没有办法让它知道别名?
琼斯的事,2014年

@SomethingJones对于您的特定用例,在中bashfind . -type f -iname '*.link' -execdir ${BASH_ALIASES[md]} -i {} \;无需cat使用wget,它具有-i用于从文件中读取URL 的标志。这也与您最初的问题有所不同(因为您似乎只对命名的文件感兴趣,.link而对可能存在的任何其他文件不感兴趣)。
muru 2014年

您知道如何使用zsh吗?我尝试了您给我的内容,但出现“错误替换”错误。另外,我如何能够提取.link文件的内容?我知道我在这种情况下不需要它,但我想我会很快的。
琼斯的事

2
cd -P .
for dir in ./*/
do cd -P "$dir" ||continue
   printf %s\\n "$PWD" >&2
   command && cd "$OLDPWD" || 
! break; done || ! cd - >&2

上面的命令不需要做任何子shell,它只是通过交替使用$OLDPWD和来跟踪其在当前shell中的进度$PWD。当cd -外壳交换目录时,基本上交换这两个变量的值。它还会在stderr上工作时为每个目录打印名称。

我只是重新看了一下,并决定我可以在错误处理方面做得更好。它会跳过一个它无法进入的目录cd-并cd输出一条有关为什么选择stderr的消息- break如果您command执行失败或运行command以某种方式影响了它返回原始目录的能力,它将带有一个非零的退出代码。- $OLDPWD。在这种情况下,它也会执行cd -最后-将生成的当前工作目录名称写入stderr。


1
for D in ./*; do
    if [ -d "$D" ]; then
        cd "$D"
        run_something
        cd ..
    fi
done
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.