[英]reuse command output multiple times in bash script
我有一个 bash 脚本,它运行几个类似的查找命令并将 output 读入变量:
f_list=`find /foo -name bar | sort`
f_number=`find /foo -name bar | wc -l`
f_first=`find /foo -name bar | sort | head -n 1`
所有这些都按预期工作。
假设“查找”命令很昂贵(时间方面),是否有一种巧妙的方法可以为其他结果重新使用其中一个结果?
我尝试过(但失败了)是:
f_list=`find /foo -name bar | sort`
f_number=`echo "$f_list" | wc -l`
f_first=`echo "$f_list" | head -n 1`
这不起作用,但我希望它显示我想要实现的目标。
似乎将结果放入变量中会破坏原始 output 的某些格式,当再次发送到其他命令时会破坏内容。
有什么聪明的方法可以实现我想要的吗?
编辑
我创建了一个可以重新创建的完整工作示例。 在我的工作目录中,我有一个文件夹“foo”,其中包含 3 个文件“bar1”、“bar2”、“bar3”。
find_result=`find ./foo -type f -iname "bar*" | sort`
find_count1=`echo "$find_result" | wc -l`
echo "$find_result"
echo $find_count1
find_count2=`find ./foo -type f -iname "bar*" | wc -l`
find ./foo -type f -iname "bar*"
echo $find_count2
结果是预期的
./foo/bar1
./foo/bar2
./foo/bar3
3
./foo/bar3
./foo/bar2
./foo/bar1
3
但是当结果为空时(我修改了搜索条件,什么也没找到)
find_result=`find ./foo -type f -iname "bor*" | sort`
find_count1=`echo "$find_result" | wc -l`
echo "$find_result"
echo $find_count1
find_count2=`find ./foo -type f -iname "bor*" | wc -l`
find ./foo -type f -iname "bor*"
echo $find_count2
两个结果不同(注意“1”前面的空结果行)
1
0
因此,我认为罪魁祸首是 echo 命令中的额外换行符。 因此我删除了它(注意第二行中的“-n”):
find_result=`find ./foo -type f -iname "bor*" | sort`
find_count1=`echo -n "$find_result" | wc -l`
echo "$find_result"
echo $find_count1
find_count2=`find ./foo -type f -iname "bor*" | wc -l`
find ./foo -type f -iname "bor*"
echo $find_count2
这解决了空结果的问题
0
0
但是现在当有结果时,“wc -l”计数错误,所以
find_result=`find ./foo -type f -iname "bar*" | sort`
find_count1=`echo -n "$find_result" | wc -l`
echo "$find_result"
echo $find_count1
find_count2=`find ./foo -type f -iname "bar*" | wc -l`
find ./foo -type f -iname "bar*"
echo $find_count2
产量在
./foo/bar1
./foo/bar2
./foo/bar3
2
./foo/bar3
./foo/bar2
./foo/bar1
3
所以问题是一个换行符,我认为必须有一个简单的解决方案,以避免空和非空查找结果之间的差异。 我有一种错过了一些非常简单的东西的感觉。
使用变量重用find
的 output 应该可以工作。 也许您的文件名中有反斜杠会被echo
解释(尽管默认情况下不应该发生这种情况)。 如果是这样,则使用printf %s "$f_list"
代替。 但如果没有完整的可验证示例,我们无法确定。
但是,在这种特定情况下,您也可以切换到以下命令,如果没有文件匹配,这也是安全的,并且在某些文件具有多行文件名的非常不寻常的情况下也是安全的。
shopt -s globstar dotglob nullglob
list=(/foo/**/bar)
number=${#list[@]}
first=${list[0]}
另一种方法是使用临时文件。 那将是这样的:
temp=$(mktemp /tmp/prefixXXXXXXXXXXX)
find /foo -name bar | sort > $temp
f_number=`wc -l $temp`
f_first=`head -n 1 $temp`
rm -f $temp
使用数组存储find -print0 | sort -z
返回的null
分隔列表 find -print0 | sort -z
:
#!/usr/bin/env bash
# map null delimited output of command-group into the f_list array
mapfile -t f_list < <(find /foo -name bar -print0 | sort --zero-terminated)
# Number of entries in the f_list array
f_number=${#f_list[@]}
# First entry of the f_list array
f_first=${f_list[0]}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.