我正在制作一个脚本来简化我的日常任务。每天,我都必须在公司服务器内查找一些东西。没关系,但是现在,他们已将每个对象分离到子目录中。我正在寻找一种解决方案,其中我现有的 shell 脚本将在某个目录内的每个子目录中重复执行。我该怎么做呢?我对 Linux 还很陌生,仍在学习中。
这是我的脚本:
#!/bin/bash
MainDir=/path/to/dir/containing/subdirs
# cd into dir
cd $MainDir
for dir in $(ls); do
#fetch start time of uut
grep -i "01_node_setup" $dir/his_file | tail -1 >> /home/xtee/sst-logs.out
#check if sysconfig.out exists
if [ -f $dir/sysconfig.out];
then
grep -A 1 "Drive Model" $dir/sysconfig.out | tail -1 >> /home/xtee/sst-logs.out
else
grep -m 1 "Pair0 DIMM0" $dir/node0/trans_file_prev/*setupsys* | tail -1 >> /home/xtee/sst-logs.out
fi
done
#cd back to where we started
cd $OLDPWD
一个好人帮助我编写了脚本,上面的脚本就是这样出来的。但是它工作正常,显示 sst-logs.out 文件binary file /some/subdirectory/
而不是 grep 的输出。脚本中有什么问题?
答案1
找到会拯救你:
find /your/dir/with/subdirs -type d -exec sh -c 'cd "{}" ; /path/to/your/script.sh ;' \;
答案2
您的脚本中有几个问题。
cd $MainDir
最好做这个cd "$MainDir"
。这并不重要,但这是一个值得养成的好习惯。如果变量扩展不加引号,则变量的值将被拆分为单词,并且每个单词都被视为 shell 通配符模式;因此,如果$MainDir
包含空格或\[?*
.添加双引号永远不会有什么坏处(除非您希望发生拆分和文件名匹配),并且可以避免这些额外的扩展。命令替换 ( ) 也是如此$(somecommand)
。始终在变量和命令替换两边加上双引号除非你知道你想要分割和文件名匹配。
for dir in $(ls); do
不解析输出ls
。您几乎不需要ls
在脚本中使用。如上所述,命令替换的结果被分成被视为通配符模式的单词,因此$(ls)
除了ls
可能会破坏不可打印字符之外,还会破坏空格和通配符。 shell 内置了列出目录中的文件名的功能:
for dir in *; do
如果这样做for dir in */; do
,则仅匹配当前目录的子目录,而不匹配其他类型的文件。
if [ -f $dir/sysconfig.out];
括号两边都需要有空格,除非它旁边的字符是 shell 标点符号:();&|<>
。再次,在变量替换两边加上双引号(这适用于所有其他有变量替换的地方):if [ -f "$dir/sysconfig.out" ];
#cd back to where we started cd $OLDPWD
这是没用的:进程即将退出,更改其当前目录不会影响任何内容。请注意,每个进程都有自己的当前目录:在脚本中更改它不会影响调用该脚本的程序。
回到你问这个问题的原因,目前尚不清楚你想要什么。 “ binary file /some/subdirectory/
”没有多大意义:您不会通过目录收到此消息。为了获得更好的帮助,请复制粘贴错误消息。你应该总是复制粘贴错误消息当您在线寻求帮助时。
从您的描述来看,文件似乎已更深一层目录。如果是这种情况,请将行更改for dir in */; do
为
for dir in */*/; do
答案3
有多种方法可以做到这一点。您可以在 for 循环中运行现有脚本,或者使用 find 和 xargs,甚至可以使用 grep 的-r
又名--recursive
选项。
最简单的可能就是围绕现有脚本编写一个 for 循环包装器。例如:
#! /bin/bash
cd /path/to/top/level/directory
for d in */ ; do
pushd $d
# call your script here
popd
done
答案4
对@rush的建议稍作改进,您可以通过执行以下操作来避免添加命令,find
而不是使用开关:-exec
cd
find /path/to/dir/containing/subdirs -type d -execdir /path/to/your/script.sh \;
这样您就可以for
完全避免原始脚本中的循环。