繁体   English   中英

在 bash 脚本中多次重用命令 output

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM