Bash 执行简单grep脚本时发生意外错误
我试图从一系列很长的文件中收集一行。不幸的是,我需要从1600个不同目录中的同名文件中提取同一行。目录结构如下所示 目录jan10包含已执行的bash脚本和名为18-109的目录。目录18-109分别包含名为18A、18B、…、18H的目录。在每个目录中都有一个文件“target.out”,我们希望从中获取信息。以下是我为访问此信息而编写的代码:Bash 执行简单grep脚本时发生意外错误,bash,grep,cd,Bash,Grep,Cd,我试图从一系列很长的文件中收集一行。不幸的是,我需要从1600个不同目录中的同名文件中提取同一行。目录结构如下所示 目录jan10包含已执行的bash脚本和名为18-109的目录。目录18-109分别包含名为18A、18B、…、18H的目录。在每个目录中都有一个文件“target.out”,我们希望从中获取信息。以下是我为访问此信息而编写的代码: for i in $(cat ~/jan10/list.txt); do cd $i cd *A grep E-SUM-O
for i in $(cat ~/jan10/list.txt);
do
cd $i
cd *A
grep E-SUM-OVERALL target.out | cut -c 17-24 > ../overallenergy.out
cd ../*B
grep E-SUM-OVERALL target.out | cut -c 17-24 >> ../overallenergy.out
cd ../*C
grep E-SUM-OVERALL target.out | cut -c 17-24 >> ../overallenergy.out
cd ../*D
grep E-SUM-OVERALL target.out | cut -c 17-24 >> ../overallenergy.out
cd ../*E
grep E-SUM-OVERALL target.out | cut -c 17-24 >> ../overallenergy.out
cd ../*F
grep E-SUM-OVERALL target.out | cut -c 17-24 >> ../overallenergy.out
cd ../*G
grep E-SUM-OVERALL target.out | cut -c 17-24 >> ../overallenergy.out
cd ../*H
done
在本例中,list.txt包含不同行上的数字18-109。“list.txt”的示例如下所示:
17
18
19
20
21
22
23
24
25
出乎意料的是,此代码根本无法工作,它返回错误:
./testscript.sh: line 8: cd: 18: No such file or directory
./testscript.sh: line 11: cd: *A: No such file or directory
它为每个编号目录和每个字母子目录返回此错误。有人知道我做错了什么吗?我会回答任何问题,如果不清楚,我再次道歉。grep命令本身就可以工作,所以我想其中一个“cd”命令可能有问题,但我不确定。代码正在jan10目录中执行 现在我更好地理解了您的需求(我的错),这里有一个更充实的解决方案
prompt$ cat simpleGrepScript.sh
#!/bin/bash
if ${testMode:-true} ; then
echo "processing file $1 into outfile ${1%/*}/../overallenergy.out" 1>&2
else
[[ -f "$1" ]] && grep 'E-SUM-OVERALL' "$1" > ${1%/*}/../overallenergy.out || echo "no file "$1" found" 1>&2
fi
跑
如果testMode的输出
"processing file $1 into outfile ${1%/*}/../overallenergy.out"
看起来正常,然后更改为${testMode:-false}
如果它看起来不正确,将mininum错误示例作为注释发布,我将看看是否可以修复它
如果您的路径名中有空格,我们必须返回并添加更多选项到find
和xargs
IHTH.定义一个shell函数,该函数对于给定目录,查找所有底层目标,对于每个目标输出,在
stdout
上,使用一个合适的命令
% gen_greps () {
find $1 -name target.out | while read fname ; do
printf "grep E-SUM-OVERALL $fname | "
printf "cut -c 17-24 > "
printf "$(dirname $fname)/overallenergy.out\n"
done
}
%
干一次
% gen_greps jan10
...
grep E-SUM-OVERALL jan10/29/29H/target.out | cut -c 17-24 > jan10/29/29H/overallenergy.out
...
%
如果我们看到的是我们想要的,那么将命令传递给shell执行
% gen_greps jan10 | sh
%
仅此而已(?)不要以这种方式使用
for
。要执行for
,必须首先处理cat
命令,如果文件名中有空格,则for
将失败。另外,在执行的时,很可能会使命令行过载
改为使用while read
循环,该循环效率更高,对文件名问题也更宽容:
while read dir
do
....
done < ~/jan10/list.txt
我没有任何数据,所以很难实际测试。也许我可以简单地使用awk
中的字段,而不是substr
。或者我的substr
命令可能已关闭。您不需要cd
从不同的目录复制grep文件。只需在grep命令中包含文件的路径。这些错误意味着这些目录不存在于您认为应该存在的地方。确认你认为确实存在的目录。你能分享~/jan10/list.txt
的一部分内容吗?find/base/path/of/proj/data-name target.txt | xargs simpleGrepScript.sh>overallenergy.out
其中simpleGrepScript.sh只是grep-E。。“$@”
是否执行此任务?祝你好运。我相信我概述的内容将在1000多个目录中搜索文件target.out
,并在这些文件中搜索“E-SUM-OVERALL”。我没有包括| cut-c..
,但是编辑simpleGrepScript.sh
应该很简单(我发现-E
是不需要的)。请阅读有关xargs的内容,它旨在管理非常大的文件/目录列表。(我不喜欢把答案贴在不能按问题的规模测试的地方)。祝你好运
% gen_greps jan10 | sh
%
while read dir
do
....
done < ~/jan10/list.txt
while read dir
do
find $dir -name "target.out" -type f \
-exec awk '/E-SUM-OVERALL/ {print substr $0, 17, 8}' {}\;
done < ~/jan10/list.txt > overallenergy.out