Bash

Bash 腳本一般問題

  • May 22, 2019

我要處理的第一部分只是創建一個名為 command_manuals 的文件夾,其中包含 bash shell 中所有可用命令的文本文件副本,文件名本身就是命令名。除了一些不影響的不尋常錯誤消息腳本從實現它的目標開始,這部分我已經設法得到了,但我更願意先解決最嚴重的問題,所以我現在就把它排除在外。

那些沒有可用手冊的人仍然有空的文本文件,這給我帶來了第二部分的目標,即刪除這些“0 大小的文本文件”並編譯一個我想在以後使用的列表,檢查“undocumented man 7”和其他部分,每次我執行 apt-update 並使用一個眾所周知的模式搜尋包來查看是否添加了關於那些缺少手冊的命令的新內容,ra、ra、ra 反正在我之前並不重要克服第二部分的這個戲劇,到目前為止,我已經成功地將一個 if 條件寫入 for 循環,它只是列印出大小為零的文件夾內容的子集,但是當我嘗試重播這個基本迴聲時,麻煩就開始了刪除空文件的“then”和“fi”之間的命令。

但這也給我帶來了一個額外的問題,涉及我注意到的另一件奇怪的事情,即按我的意願工作的基本模板腳本缺少標準的 #!/bin/bash,它始終是我的 .sh 腳本的第一行所必需的。以前的經驗,為什麼?

template_for_if_delete.sh

TOTALnum=$(wc -l < filesizes.txt);
for i in `seq 1 $TOTALnum`;
do
size=$(sed -n ''$i','$i'p' filesizes.txt)
if [ $size -eq 0 ];
then
echo $(sed -n ''$i','$i'p' filenames.txt);
fi
done;

到目前為止,我有第二個任務的實際腳本:

secondpart.sh

#!/bin/bash
cd;
cd command_manuals;
rm filenames.txt;
ls -1 > filenames.txt;
TOTALnum=$(wc -l < filenames.txt);
for i in `seq 1 $TOTALnum`;
do filename=echo $(sed -n ''$i','$i'p' filenames.txt);
size=$(stat -c '%s' $filename);
if [ $size -eq 0 ];
then
rm $(locate $(sed -n ''$i','$i'p' filenames.txt));
fi
done;

它產生輸出(根據上面 for 循環中定義的數量重複多次):

Try 'stat --help' for more information.
./secondpart.sh: line 9: [: -eq: unary operator expected
./secondpart.sh: line 8: x86_64-linux-gnu-gold.txt: command not found
stat: missing operand

然後,我嘗試將 if 語句中的變數“大小”更改為複雜的參數擴展:

#!/bin/bash
cd;
cd command_manuals;
rm filenames.txt;
ls -1 > filenames.txt;
TOTALnum=$(wc -l < filenames.txt);
for i in `seq 1 $TOTALnum`;
do filename=echo $(sed -n ''$i','$i'p' filenames.txt);
size=$(stat -c '%s' $filename);
if [ ${#size} -eq 0 ];
then
rm $(locate $(sed -n ''$i','$i'p' filenames.txt));
fi
done;

這產生了相關的輸出,詢問我是否要刪除一些隨機不相關的東西,此時我決定好的,我最好在搞砸執行良好的虛擬機之前發布一個問題:

./secondpart.sh: line 8: filenames.txt: command not found
stat: missing operand
Try 'stat --help' for more information.
rm: missing operand
Try 'rm --help' for more information.
./secondpart.sh: line 8: file-roller.txt: command not found
stat: missing operand
Try 'stat --help' for more information.
rm: missing operand
Try 'rm --help' for more information./code>
./secondpart.sh: line 8: filesizes.txt: command not found
stat: missing operand
Try 'stat --help' for more information.
rm: missing operand
Try 'rm --help' for more information.
./secondpart.sh: line 8: file.txt: command not found
stat: missing operand
Try 'stat --help' for more information.
rm: cannot remove adammvirtual/Win10UbuntuVM001_apt_sources_file.txt':
No such file or directory
rm: cannot remove '/home/adamvirtual/mapfile.txt': No such file or directory
rm: remove write-protected regular file '/usr/share/doc/alsa-base/driver/Procfile.txt.gz'?

我按ctrl+C 以逃避提示。

問題在./secondpart.sh: line 8,應該設置$filename

stat並且rm$filename爭論,所以他們在抱怨。這些錯誤是後續行動。

所以你需要修復第 8 行。

您幾乎應該總是set -euo pipefail在腳本的開頭讓它們在第一個錯誤時退出,從而防止後續錯誤。


但總的來說,您的腳本過於復雜,使用wc,for循環並且sed不是逐行讀取文件的正確方法。

而不是stat -c %s用來確定文件大小是否為零,您可能想要使用文件測試運算符 -s,它正是這樣做的(實際上檢查相反,如果文件大小為零)。

使案例如:

xargs -a filenames.txt -I{} sh -c '[ -s "$1" ] || rm -i "$1"' xargs-sh {}

或者

readarray filenames < filenames.txt
for filename in "${filenames[@]}"; do
   [ -s "$filename" ] || rm -i "$filename"
done

或者

while IFS= read -r filename; do
   [ -s "$filename" ] || rm -i "$filename"
done < filenames.txt

通常,在文本文件中逐行使用文件名並不是一個好主意,因為文件名允許在其名稱中包含換行符。相反,您應該始終使用空字元 ( \0) 作為文件分隔符。

引用自:https://unix.stackexchange.com/questions/520300