我不熟悉 bash 腳本。也許這是一個愚蠢的問題。但我找不到答案。我正在撰寫一個 bash 腳本,它模仿命令的行為,ls -sh但實際上用于du -sh獲取檔案和檔案夾大小。它對輸出進行排序。非常喜歡du -sh* | sort -h顏色。
#!/usr/bin/bash
if [ "$#" = "0" ]
then
du -sh *|awk -f /path/to/color-ls.awk|sort -h
else
du -sh $@|awk -f /path/to/color-ls.awk|sort -h
fi
其中ls-color.awk是:
# color-ls.awk
size=$1;
name=$2;
for (i=3; i<=NF; i )
{
tmp=(name " " $i);
name=tmp
}
# filename=($0 ~ /'/)? ("\"" name "\""):("'" name "'")
filename=("'" name "'")
printf $1 " "
cmd=("ls -d " filename " --color")
system(cmd)
用于ls --color為 du -sh 的輸出著色的awk 腳本
我的腳本適用于大多數檔案名,即使是包含空格的檔案名。但它有一些涉及特殊字符的問題,我不知道如何解決。
1. 不帶引數運行時:
它正在解釋包含導致錯誤的單引號的任何檔案名
sh: 1: Syntax error: Unterminated quoted string
2. 帶引數運行時:
與沒有引數相同的問題。它將帶有空格的檔案名解釋為兩個名稱。
示例:當在名為的檔案夾上使用VirtualBox VMs或*在我的主目錄中作為引數給出時,這是它的輸出:
du: cannot access 'VirtualBox': No such file or directory
du: cannot access 'VMs': No such file or directory
3.我想要的:
我希望腳本跳過特殊字符并按原樣傳遞它們 du
4. 我試過的:
我嘗試在每個檔案名前后添加雙引號
parse(){
for arg in $@
do
printf "\"$arg\"\n"
done
}
但它似乎沒有用。du 不接受附加到檔案名的引號。
du: cannot access '"VirtualBox': No such file or directory
du: cannot access 'VMs"': No such file or directory
此外,用 替換引號\'也無濟于事。也許我只是做錯了。
# du -sh $(printf "file'name\n" |sed "s/'/\\\'/g")
du: cannot access 'file\'\''name': No such file or directory
# ls file\'name
"file'name"
空格也一樣
du: cannot access 'VirtualBox\': No such file or directory
du: cannot access 'VMs': No such file or directory
5. 額外:
I'm trying to make the script works as normal ls -sh would work but with sorted output and with more accurate results when it comes to folders. but this script works like ls -sh -d when arguments are supplied to it. making lh Desktop shows the size of Desktop instead of the size of the individual files and folders inside Desktop. I believe this can be fixed with a loop that checks if each argument is a file or a folder and execute du -sh accordingly then sort.
#!/usr/bin/bash
if [ "$#" = "0" ]
then
du -sh *|awk -f /path/to/color-ls.awk|sort -h
else
for i in $@
do
if [[ -d "$i" ]]; then
du -sh $i/* |awk -f /path/to/color-ls.awk
else
du -sh "$i" |awk -f /path/to/color-ls.awk
fi
done|sort -h
fi
I'm hoping to find the optimal way to do it.
Thanks in advance.
uj5u.com熱心網友回復:
請不要在一個問題中發布這么多。每個問題請一個問題。每個問題一個腳本,等等。
確保使用 shellcheck 檢查您的腳本。它會發現你的錯誤。請參閱https://mywiki.wooledge.org/Quotes。
- 不帶引數運行時:
filename=("'" name "'")在 awk 腳本中是傳遞帶'引號的任何內容以進行system()呼叫的無效方式,因此'正如預期的那樣,您會收到未終止的錯誤,因為將有 3 個'字符。修復AWS腳本,或者用Bash重寫更好,不需要awk。也許用 Python 或 Perl 重寫它。
此外,tmp=(name " " $i);從檔案名中洗掉制表符和多個空格。這一切都意味著只使用好的檔案名。
無論如何,腳本將在檔案名中的換行符處中斷。
- 使用引數運行時:
$@經歷分詞和檔案名擴展(您應該研究的主題)。單詞拆分將輸入拆分為空格上的單詞。使用"$@". 參考擴展。
- 我想要的是:
你會這樣做 "$@"
- 我試過的:
變數內容無關緊要。你必須改變你使用變數的方式,而不是它的內容。即在變數的使用周圍使用引號。不是內容。
- 額外的:
你沒有參考擴展。使用"$i"不$i。它是"$i"/*。$1進行分詞。
最后,畢竟,您的腳本可能看起來像,使用 GNU 工具:
if (($# == 0)); then
set -- *
fi
du -hs0 "$@" |
sort -zh |
sed -z 's/\t/\x00/' |
while IFS= read -r -d '' size && IFS= read -r -d '' file; do
printf "%s " "$size";
ls -d "$file"
done
另請參閱如何查找并安全地處理包含換行符、空格或兩者的檔案名? https://mywiki.wooledge.org/BashFAQ/001。
此外,您可以鏈接任何陳述句:
if stuff; then
stuff1
else
stuff2
fi |
sort -h |
awk -f yourscriptrt
也不要重復自己 - 使用 bash 陣列:
args=()
if stuff; then
args=(*)
else
args=("$@")
fi
du -hs "${args[@]}" | stuff...
因此,sort要做的作業更少,我會將它放在 之后du,而不是在決議之后。
uj5u.com熱心網友回復:
由于您沒有包含shopt -s nullglob,因此很可能Desktop/*沒有擴展到任何奇怪的檔案,除非那里確實沒有檔案,您已nullglob在互動模式下啟用,并且du -sh實際上并未在Desktop.
您也可能Desktop/從不存在的地方呼叫腳本。
您可以添加一個除錯陳述句,列印$PWD. 您也可以嘗試使用bash -x.
在您的腳本中,我建議啟用nullglob然后修改它,因此du -sh如果目標目錄不包含任何檔案,則不會呼叫它。
就像是:
set -- "$i"/*; [[ $# -gt 0 ]] && du -sh -- "$@" ...
$@展開時也應該參考。
for i in "$@"; do
這可以簡化為for i; do,但我們將修改回圈內的位置引數,因此我們進行擴展"$@"。
您也可以選擇將擴展檔案存盤在陣列中。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/402252.html
上一篇:用更少的行制作一個shell腳本
下一篇:如何使此發布者擴展通用
