Bash

如何將命令的輸出作為參數列表傳遞給腳本?

  • April 29, 2020

我想將內容添加到目前目錄中每個文件的開頭。我需要學習如何一次從目前工作目錄中獲取所有文件名並將它們作為參數;我不需要通過手動指定每個文件作為腳本的參數來做到這一點。我想將這些新知識用於進一步的腳本。我不需要橫向或不同的解決方案。我需要學習如何獲取命令(ls)輸出並將其作為參數。我嘗試過但沒有做到這一點:

./file-edit.sh $(ls)
./file-edit.sh `ls`

這是我的有效腳本:

#!/bin/bash
lineno=2            # Append from line 2 
BAD_ARGS=85         # Error code

string0="###################################################################"
string2="#Description    :"
string3="#Date           :`date +%d-%B-%Y`"
string4="#Author         :Milos Stojanovic"
string5="#Contact:       :https://www.linkedin.com/in/xxx/"
string6="###################################################################"
# Can be any other strings

if [ ! -f $1 ]; then
       echo "Please specify at least 1 filename as an argument!"
       exit $BAD_ARGS
fi

until [ -z  "$1" ]
do
       string1="#Script Name    :$1"
       file=$1;
       sed -i ""$lineno"i $string0\n$string1\n$string2\n$string3\n$string4\n$string5\n$string6" $file
       echo "File "\'$file\'" altered at line number: $lineno"
       shift 1
done

exit 0

由於其他答案沒有解決您具體做錯了什麼,

我嘗試過但沒有做到這一點:

./file-edit.sh $(ls)

我試過你的腳本,我得到了:

$ ./file-edit.sh $(ls)
Please specify at least 1 filename as an argument!

在檢查 的輸出時ls,我注意到它首先列出了目錄。如果我移動到沒有子目錄的目錄,我得到:

$ ./file-edit.sh $(ls)
File 'a' altered at line number: 2
File 'b' altered at line number: 2
File 'c' altered at line number: 2 

因此,您檢查論點的方式是問題所在。-f僅在正常文件上成功。它看到為第一個參數提供了一個目錄,並給出了一個錯誤,指出使用者沒有提供任何文件名參數,即使他們提供了。

如果要確保至少提供了一個參數,請使用$#which 擴展為提供的參數數量:

if [ "$#" -eq 0 ]; then
 echo "Please specify at least 1 filename as an argument!"
 ...

如果要確保它們是正常文件,請在循環中進行檢查,並檢查每個文件,而不僅僅是第一個。

until [ -z  "$1" ]
do
       string1="#Script Name    :$1"
       file=$1;
       if [ -f "$file" ]; then
               sed -i "${lineno}i $string0\n$string1\n$string2\n$string3\n$string4\n$string5\n$string6" "$file"
               echo "File '$file' altered at line number: $lineno"
       fi
       shift 1
done

現在,該程式碼是在您想忽略非正常文件參數的情況下,但如果您想要的話,您可以輕鬆地將其更改為在查看非正常文件時退出。

話雖如此,不建議使用這樣的輸出ls。可以有帶有空格的文件名,而 bash 只會在空格上分割所有內容。如果你有一個文件foo bar.txt,bash 會拆分它,你的腳本會查找文件foobar.txt.

從您對問題的評論中,我看到一定有人建議您改用 glob。我真的不明白你關於它不起作用的觀點。./file-edit.sh *對我來說很好。

要在腳本中分別處理每個參數,請在您的喜歡中使用循環:

for pathname do

   # Insert code here that uses "$pathname".
   # You will not need to shift arguments.

done

要使用目前目錄中的所有名稱呼叫腳本,請使用

./script.sh ./*

shell 會將./*模式擴展為包含目前目錄中所有名稱的列表。

ls這比使用它不使用的優勢,ls因此可以處理包含任何有效字元的文件名,甚至是空格、製表符和換行符。

或者,您可以將文件名萬用字元移動到腳本本身(以避免在命令行上為腳本提供任何參數)

for pathname in ./*; do
   # Insert code here that uses "$pathname".
done

如果您的腳本需要區分引用正常文件的名稱和引用任何非正常文件(例如目錄)的名稱,請-f在循環中使用測試:

# skip non-regular files
[ ! -f "$pathname" ] && continue

這仍然會讓符號連結到正常文件。要跳過這些,請將測試更改為

if [ ! -f "$pathname" ] || [ -L "$pathname" ]; then
   # Skip non-regular files and symbolic links.
   continue
fi

其他的建議:

您可以通過在字元串中包含換行符來將多行字元串分配給變數:

boilerplate='Hello and welcome!
This is my program.
Enjoy'

要在文本文件的第二行之後插入文本,使用sed-i在此處用於就地編輯):

printf '%s\n' "$boilerplate" | sed -i '2r /dev/stdin' somefile

或者,使用此處的文件,

sed -i '2r /dev/stdin' somefile <<END_BOILERPLATE
Hello and welcome!
This is my program.
Enjoy
END_BOILERPLATE

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