Bash
循環輸出管道可防止局部變數修改
我正在嘗試編寫一個簡單的 bash 函式,該函式將多個文件和/或目錄作為其參數。這應該:
- 完全限定文件名。
- 對它們進行排序。
- 刪除重複項。
- 列印所有實際存在的內容。
- 返回不存在文件的數量。
我有一個幾乎可以完成我想要的腳本,但在排序上失敗了。腳本的返回值是正確的,但輸出不正確(未排序和重複)。如果我
| sort -u
按照指示取消註釋該語句,則輸出是正確的,但返回值始終為0
.NB 歡迎使用更簡單的解決方案來解決問題,但問題實際上是關於為什麼會在我的程式碼中發生這種情況。也就是說,為什麼添加管道似乎會阻止腳本增加變數
r
?這是腳本:
function uniqfile { local r=0 for arg in "$@" do readlink -e "$arg" || (( ++r )) done #| sort -u ## remove that comment return $r }
由於這個特性,這是一個眾所周知的 bash 陷阱:
管道中的每個命令都作為單獨的程序執行(即,在子shell 中)。
這樣修改後的變數對於子外殼來說是本地的,並且一旦回到父外殼中就不會可見。
為避免這種情況,請改寫您的程式碼以避免管道,並使用程序替換:
for arg in "$@" do readlink -e "$arg" || (( ++r )) done > >(sort -u)
強制前面的
| sort -u
位(所以整個for循環)在子程序中執行(bash需要一個’STDOUT’來重定向到sort
‘STDIN’。(網際網路似乎認為ksh
和bash
處理這種情況略有不同..第一個或最後一個管道序列中的命令被放入子shell?)這個執行緒解決了一個類似的問題,最後有一個簡潔的解決方案:http ://ubuntuforums.org/showthread.php?t=312017
摘抄
#!/bin/bash exec 3< <(du | sort -n) n=0 while read size dir; do [ $size -gt 1000 ] && ((n++)) done <&3 exec 3<&- echo "Found $n too big files"