パイプまたはコマンドライン引数からファイル名を読み取るBashスクリプト?

パイプまたはコマンドライン引数からファイル名を読み取るBashスクリプト?

私のスクリプトは、globまたはSTDIN(スペースを含む)として提供された複数のファイル名を読み、それを使用して操作を実行したいと思います。 2つの方法を別々に読むことはできますが、組み合わせることはできません。

これはコマンドラインからglobを読み込みます。

for filename in "$@"; do
    process_file "$filename"
done

これはSTDINから読み取られます。

IFS=$'\n' read -d '' -r -a filenames
for filename in "${filenames[@]}"; do
    process_file "$filename"
done

for filename in...私が本当に望むのは、これらのうちの1つを配列に読み込んでループ全体を2回繰り返す必要がないようにすることです。これが明らかな場合は申し訳ありません。私はBASHを初めて使用します。

編集:最良の方法は、与えられたパラメータからそれを読み、そうでない場合は待つことですSTDIN。どうすればいいですか?

編集:良いです。問題は私が考えたものとは異なります。問題は、process_fileにもユーザー入力が必要であることです。STDINEOFで読み取りを開始して保存し、再入力を要求する方法はありますか?

ベストアンサー1

テキスト処理ツールは通常、コマンドラインにファイル名を指定しないと、標準入力から入力を読み込みます。変数をテストして、コマンドライン引数があるかどうかを確認できます$#process_file標準入力に引数が渡されない場合は、標準入力から読み取られると仮定します。

if [ $# -eq 0 ]; then
  process_file
else
  for x; do
    process_file "$x"
  done
fi

またはprocess_file引数が必要な場合は、それを渡して/dev/stdin標準入力から読みます。

if [ $# -eq 0 ]; then set /dev/stdin; fi
for x; do
  process_file "$x"
done

コマンドライン引数なしで標準入力から読み取るファイル名のリストを要求しています。もちろん可能ですが珍しいのでお勧めできません。ユーザーは他のほとんどのツールとは異なる規則を学ぶ必要があります。それにもかかわらず、次の方法があります。

if [ $# -eq 0 ]; then
  set -f # turn off globbing
  IFS='
' # set newlines to be the only field separator
  set -- $(cat)
  set +f; unset IFS
fi
for x; do
  process_file "$x"
done

おすすめ記事