簡體   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