
該腳本有時會失敗,有時會成功(這是一種非常煩人的情況):
#!/bin/bash
set -Eeuxo pipefail
test_dir="$(mktemp -d)"
touch "$test_dir/file"{001..312}
latest_file="$(find $test_dir -type f | sort -r | head -n1)"
echo $latest_file
當它成功時,它會記錄如下內容:
++ mktemp -d
+ test_dir=/tmp/tmp.yWelcpBYB7
+ touch /tmp/tmp.yWelcpBYB7/file001 /tmp/tmp.yWelcpBYB7/file002 ... /tmp/tmp.yWelcpBYB7/file312
++ find /tmp/tmp.yWelcpBYB7 -type f
++ head -n1
++ sort -r
+ latest_file=/tmp/tmp.yWelcpBYB7/file312
+ echo /tmp/tmp.yWelcpBYB7/file312
/tmp/tmp.yWelcpBYB7/file312
當失敗時,它會記錄如下內容:
++ mktemp -d
+ test_dir=/tmp/tmp.VzTqmgpZyG
+ touch /tmp/tmp.VzTqmgpZyG/file001 /tmp/tmp.VzTqmgpZyG/file002 ... /tmp/tmp.VzTqmgpZyG/file312
++ find /tmp/tmp.VzTqmgpZyG -type f
++ sort -r
++ head -n1
+ latest_file=/tmp/tmp.VzTqmgpZyG/file312
請注意該echo $latest_file
行是不是即使它出現在 xtrace 中也在這裡執行
如果我使用 10,000 個文件,我就無法成功運行,所以我懷疑這與頭停止尋找早期的。
#!/bin/bash
set -Eeuxo pipefail
test_dir="$(mktemp -d)"
touch "$test_dir/file"{0000..9999}
latest_file="$(find $test_dir -type f | sort -r | head -n1)"
echo $latest_file
如果我抑制錯誤停止(使用設定+e),它成功了:
#!/bin/bash
set -Eeuxo pipefail
test_dir="$(mktemp -d)"
touch "$test_dir/file"{0000..9999}
set +e
latest_file="$(find $test_dir -type f | sort -r | head -n1)"
set -e
echo $latest_file
為什麼這個腳本不能可靠地記錄最新文件?
答案1
問題是-e
.為什麼?-e
如果進程以非零退出程式碼退出,則 bash 中止(完整規則有點複雜)。如果有管道,則僅計算最後一個命令。
您head -n1
在內部創建了一個錯誤情況,因為它必須破壞管道(您可以使用 檢查它strace
)以忽略 的其餘輸出sort
。
因此,為了使您的腳本可靠地使用-e
,您可以cat
在管道末尾添加 a 。head
仍然會破壞管道,但由於它不再是其中的最後一個命令,因此 不會考慮它-e
。cat
是管道的無操作:
#!/bin/bash
set -Eeuxo pipefail
test_dir="$(mktemp -d)"
touch "$test_dir/file"{0000..9999}
latest_file="$(find $test_dir -type f | sort -r | head -n1 | cat)"
echo $latest_file
請檢查為什麼 set -e (或 set -o errexit 或 trap ERR)沒有達到我的預期?了解為什麼-e
這個功能如此不穩定以及它可能帶來什麼樣的問題。最後還有很多例子。我最喜歡的:
#!/bin/bash
set -e
foo=$(expr 1 - 1)
echo survived
它會不是列印倖存下來,該行將不會被執行。但是,如果你有foo=$(expr 2 - 1)
,那麼echo
就會被執行!
您最好實施自己的錯誤檢查,-e
這不是最好的解決方案。