Linux Shell 指令長度限制問題與解決的替代方案

在 Linux 中的指令通常都有一些參數可以指定,而在 Shell 中一行指令的長度是有上限的,在大部分的狀況下,這個限制通常是不會造成什麼問題的,不過在某些參數特別多的狀況下,可能就會碰到這個限制,例如要用 rmmv 指令刪除或搬移很多檔案的時候,如果指定的檔案數量太多,有可能就會發生參數過長的錯誤,就像這樣:
Argument list too long


在不同的系統中,命令列的長度上限是不同的,這裡介紹如何找出自己系統的命令列長度上限,並且教大家在撰寫指令稿時,如何使用一些替代方案避開參數過長的問題。

查詢命令列長度上限

在一般的 UNIX、Linux 或 BSD 系統中,如果想查詢命令列的長度上限,可以使用 getconf 這個指令:
getconf ARG_MAX
輸出會像這樣:
2097152
而在 BSD 的系統中,也可以使用 sysctl 指令:
sysctl kern.argmax
這個輸出會像這樣:
kern.argmax=262144

而上面這些值是整個命令列的長度上限,事實上還包含了一些環境變數,如果想知道實際上在執行指令時,可以輸入的長度,可以用這個方式扣掉環境變數用掉的部分:
echo $(( $(getconf ARG_MAX) - $(env | wc -c) ))
輸出為:
2095122
這個值就是輸入指令時真正可以用的最大長度。

指令太長的解決方式

如果你要執行的指令長度超過容許的上限,基本上有兩種方式可以解決:
  • 使用 findxargs 指令。
  • 使用 Shell 的 forwhile 迴圈。

使用 find 指令,列出 /nas/data/accounting/ 的檔案:
find /nas/data/accounting/ -type f -exec ls -l {} \;
刪除 /nas/data/accounting/ 的檔案:
find /nas/data/accounting/ -type f -exec /bin/rm -f {} \;

使用 xargs 的方式:
echo /nas/data/accounting/* | xargs ls -l
echo /nas/data/accounting/* | xargs /bin/rm -f

使用 while 迴圈:
ls -1 /nas/data/accounting/ | while read file; do mv /nas/data/accounting/$file /local/disk/ ; done

將上面的各種方式放在一起:
find /nas/data/accounting/ -type f |
  while read file
  do
    mv /nas/data/accounting/$file /local/disk/
  done

參考資料:nixCraft
本站已經搬家了,欲查看最新的文章,請至 G. T. Wang 新網站