遍历Unix shell脚本中的所有子目录并执行某些操作


17

我希望我的Shell脚本访问主目录中的所有子目录。在目录中执行某些操作,将输出发送到假脱机文件,然后继续下一个目录。考虑主目录= / tmp子目录= ABCD(四个子目录)


2
好的,请向我们展示您的脚本。它的哪一部分给您带来麻烦?
terdon

Answers:


22

使用for循环:

for d in $(find /path/to/dir -maxdepth 1 -type d)
do
  #Do something, the directory is accessible with $d:
  echo $d
done >output_file

它仅搜索目录的子目录/path/to/dir。请注意,如果目录名称包含空格或特殊字符,则上面的简单示例将失败。一种更安全的方法是:

find /tmp -maxdepth 1 -type d -print0 |
  while IFS= read -rd '' dir; do echo "$dir"; done

或简单地说bash

for d in /path/to/dir/*; do
  if [ -d "$d" ]; then
    echo "$d"
  fi
done

(请注意,与此相反find,它还考虑了目录的符号链接,但排除了隐藏的链接)


1
至少要指出与处理find类似输出相关的限制和风险。
斯特凡Chazelas

嗨...我试图在$(查找/备份/ ASHISH -maxdepth 1 -type d)中为d循环以下运行ls -l | awk'{print $ 9}'| grep CC * _ date +"%m%d20%Y"| xargs echo echo $ d
Ashish

嗨...我在下面尝试了循环。$(查找/备份/ ASHISH -maxdepth 1 -type d)中的d做ls -l | awk'{print $ 9}'| grep CC * _ date +"%m%d20%Y"| xargs echo echo $ d预期结果是ls -ltr来自所有子目录。以上循环无法正常工作
Ashish

1

我是一个bash新手,但是是UN * X的资深人士。尽管毫无疑问,这可以在Bash shell脚本中完成,但是在过去,我们曾经find [-maxdepth <levels>] <start-dir> -exec <command> ;实现此目的。您可以做一个,man find然后玩耍,直到有人告诉您如何做bash


我在这里的“纲要”答复获得了赞成票,对此我感到很受宠若惊。但是,为什么下面@chaos的答案被否决了?(作为本委员会的新手,我不能针对他的回答发表评论,只能针对我自己的评论发表评论。)他的第二个建议对于Shell脚本解决方案是正确的,并且避免了运行外部find命令的开销。
JonBrave 2015年

他的第二个确实是正确的。如果目录名称包含空格或特殊字符(例如反斜杠),则他的第一个操作将失败。请参阅我对他的答案所做的修改,以获取安全版本。
terdon

我同意。这是我赞美的他的第二个,只有壳的答案。
JonBrave 2015年

我知道,我只是在解释那票(我没有投过票)。
terdon


1

看起来您想要每个子目录下的文件名;在ls -l | awk没有足够强大的,因为如果这些东西包含文件名的空白和/或换行符?find即使对于finds而言,以下代码也可以正常工作-maxdepth

find . ! -name . -type d -prune -exec sh -c '
   cd "$1" && \
   find "." ! -name . -prune  -type f
' {} {} \;

0

我找到了解决方案。下面的find命令符合我的要求。

find . -maxdepth 1 -type d \( ! -name . \) -exec bash -c "cd '{}' && ls -l |awk '{ print $9 }' |grep `date +"%m%d%Y"`|xargs echo" \;

0

也可以使用ls,grep和tr

for dir in $(ls -1FA | grep / | tr -d /); do echo $dir/something; done

ls -1FA | grep / | tr -d / | while IFS= read -r TD; do echo $TD/something; done

如果您的ls缺少上述选项,则du / sed也可以用作选择器

du --max-depth=1 | sed -e 's/^.*\.\///' | grep -v '\.$'

注意这些示例返回隐藏目录并排除父目录和当前目录可能很重要


1
(1)  默认情况下,当标准输出是管道时,ls每行写一个文件(该-1选项指定)(因此它在回答中是多余的)。(2)解析的输出ls是一个坏主意-请参阅 thisthis。如果目录名称中包含空格(或换行符),则第一个答案将失败;如果目录名称中包含换行符,则所有答案均将失败。(3)"$dir"除非您有充分的理由不这样做,否则您应该始终引用shell变量(例如),并且您确定自己知道自己在做什么。
斯科特,

好点斯科特。对于许多没有过分命名的dirs的系统,我留下答案,我认为它可能仍然有用。
JGurtz
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.