linux shell 怎么打开文件夹,关于bash:如何进入每个目录并执行命令?

我如何编写一个bash脚本,它遍历parent_directory内部的每个目录并在每个目录中执行命令。

目录结构如下:

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.

托德(Todd)发布的答案对我有帮助。

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

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

并且,如果您只想在某些文件夹中运行命令,则:find FOLDER* -maxdepth 0 -type d \( ! -name . \) -exec bash -c"cd {} && pwd" \;

我必须做-exec bash -c cd"$0" && pwd {} \;,因为某些目录包含单引号和一些双引号。

您还可以通过添加-mindepth 1来省略当前目录

如何将其更改为接受" git remote get-url origin"之类的命令而不直接使用pwd的函数?

disd(){find . -maxdepth 1 -type d \( ! -name . \) -exec bash -c cd"{}" &&"$@" \;}不起作用。

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

for d in [0-9][0-9][0-9]

do

( cd"$d" && your-command-here )

done

(和)创建一个子外壳,因此在主脚本中不会更改当前目录。

这里没有关系,因为通配符不匹配数字以外的任何内容,但是在一般情况下,您基本上总是希望将目录名放在循环内的双引号中。 cd"$d"会更好,因为它可以转移到通配符确实匹配名称包含空格和/或shell元字符的文件的情况。

(这里的所有答案似乎都具有相同的缺陷,但这在投票最多的答案中最重要。)

另外,绝大多数命令实际上并不关心您在哪个目录中执行它们。 for f in foo bar; do cat"$f"*.txt; done >output在功能上等效于cat foo*.txt bar*.txt >output。但是,ls是一个命令,根据传递参数的方式,它产生的输出会稍有不同。类似地,如果从子目录运行它,则输出相对文件名的grep或wc也将有所不同(但通常由于这个原因,您要避免进入精确的子目录)。

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

find . -type d -execdir realpath"{}" ';'

或(根据@gniourf_gniourf注释):

find . -type d -execdir sh -c 'printf"%s/%s

""$PWD""$0"' {} \;

注意:可以使用${0#./}代替$0来固定./在前面。

或更实际的例子:

find . -name .git -type d -execdir git pull -v ';'

如果要包括当前目录,使用-exec甚至更简单:

find . -type d -exec sh -c 'cd -P --"{}" && pwd -P' \;

或使用xargs:

find . -type d -print0 | xargs -0 -L1 sh -c 'cd"$0" && pwd && echo Do stuff'

或@gniourf_gniourf建议的类似示例:

find . -type d -print0 | while IFS= read -r -d '' file; do

# ...

done

上面的示例支持名称中带有空格的目录。

或通过分配到bash数组中:

dirs=($(find . -type d))

for dir in"${dirs[@]}"; do

cd"$dir"

echo $PWD

done

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

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

mapfile -t -d '' dirs <

还是不推荐使用的方法(涉及解析ls):

ls -d */ | awk '{print $NF}' | xargs -n1 sh -c 'cd $0 && pwd && echo Do stuff'

上面的示例将忽略当前目录(按OP的要求),但是它将破坏带有空格的名称。

也可以看看:

Bash:针对SO中的每个目录

如何在当前路径中输入每个目录并执行脚本?在SE Ubuntu

在不使用显式循环的情况下将find的输出放入数组中的唯一正确方法将在带有mapfile -t -d dirs < 的Bash 4.4中提供。在此之前,您唯一的选择是使用循环(或将操作推迟到find)。

实际上,您实际上并不需要dirs数组;您可以像这样安全地循环find的输出:find . -type d -print0 | while IFS= read -r -d file; do ...; done。

@gniourf_gniourf我是视觉的,总是尝试查找/使看起来简单的东西。例如。我已经编写了这个脚本,使用bash数组对我来说很容易理解(通过将逻辑分成较小的部分,而不是使用管道)。引入其他管道IFS,read,给人留下了额外的复杂性。我不得不考虑一下,也许有一些更简单的方法可以做到。

如果您更容易理解是破碎,那么是的,有更简单的方法。现在不用担心,随着您习惯它们,所有这些IFS和read(正如您所说的)都变成了第二自然……它们是编写脚本的规范和惯用方式的一部分。

顺便说一句,您的第一个命令find . -type d -execdir echo $(pwd){} ;并没有完成您想要的操作($(pwd)甚至在find执行之前就已展开)…

@gniourf_gniourf当Ive在扩展pwd之前尝试运行pwd时,尽管find返回不同的目录,它也无法按预期方式运行(它只显示相同的目录)。

如果顶层文件夹是已知的,则可以这样写:

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

在$上(尽可能多地玩);您可以根据需要放置尽可能多的代码。

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

干杯,

这里有几个" ls的无用使用"的实例-您可以改为for dir in $YOUR_TOP_LEVEL_FOLDER*。

好吧,也许它在一般意义上是无用的,但是它允许直接在ls中进行过滤(即,所有以.tmp结尾的目录)。那就是为什么我使用ls $dir表达式

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

ls -d */ | xargs -I {} bash -c"cd '{}' && pwd"

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

我不知道为什么还没有提出这个建议,但是我找到了迄今为??止最简单的脚本。谢谢

别客气 !

for dir in PARENT/*

do

test -d"$dir" || continue

# Do something with $dir...

done

+1表示测试-d。帮助过我。

这很容易理解!

虽然一个内衬适合快速和肮脏的用法,但我更喜欢下面更详细的版本来编写脚本。这是我使用的模板,可以处理许多极端情况,并允许您编写更复杂的代码以在文件夹上执行。您可以在函数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"

您可以使用

find .

搜索当前目录中的所有文件/目录

比您可以像这样通过管道传递xargs命令的输出

find . | xargs 'command here'

这不是要问的。

我不了解文件的格式,因为您只想遍历文件夹...您是否正在寻找类似的东西?

cd parent

find . -type d |while read d; do

ls $d/

done

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

您需要再次更改备份目录,或者在子shell中执行cd。

谢谢您的纠正,马克。 Subshel??l非常适合这里。

Downvote:编辑丢失了cd,因此此代码实际上没有做任何有用的事情。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值