回答:
シェルが(特に)bashの場合、のショートカット$(cat afile)
は$(< afile)
なので、次のように記述します。
mycommand "$(< file.txt)"
「コマンド置換」セクションのbashマニュアルページに記載されています。
または、コマンドをstdinから読み取って、次のようにします。 mycommand < file.txt
<
演算子を使用するのは簡単ではありません。これは、シェル自体がcat
リダイレクトプロパティのバイナリを実行するのではなく、リダイレクトを実行することを意味します。
"$(…)"
、の内容は、引数としてfile.txt
でmycommand
はなく、の標準入力に渡されます。コマンドを実行し、出力を文字列として返す"$(…)"
ことを意味します。ここで「コマンド」はファイルを読み取るだけですが、より複雑になる可能性があります。
すでに述べたように、バックティックまたはを使用できます$(cat filename)
。
言及されなかった、そして私が注意することが重要だと思うのは、シェルが空白によってファイルの内容を分解し、引数としてコマンドに見つけた各「単語」を与えることを覚えておかなければならないということです。また、空白やエスケープシーケンスなどを含めることができるようにコマンドライン引数を引用符で囲むこともできますが、ファイルからの読み取りは同じことを行いません。たとえば、ファイルに次のものが含まれているとします。
a "b c" d
取得する引数は次のとおりです。
a
"b
c"
d
各行を引数として取得する場合は、while / read / do構文を使用します。
while read i ; do command_name $i ; done < filename
read -r
バックスラッシュエスケープシーケンスを展開する場合を除いて、読み取りを行う必要があります。特に、NULは、改行よりも安全に使用できる区切り文字です。特に、渡す引数がファイル名のようなもので、リテラルの改行が含まれる場合があります。また、IFSをクリアしないと、先頭と末尾の空白がから暗黙的にクリアされi
ます。
command `< file`
stdinのコマンドにファイルの内容を渡しますが、改行を取り除きます。つまり、各行を個別に繰り返すことができませんでした。そのためには、「for」ループを使用してスクリプトを記述できます。
for line in `cat input_file`; do some_command "$line"; done
または(複数行バリアント):
for line in `cat input_file`
do
some_command "$line"
done
または(の$()
代わりに複数行のバリアント``
):
for line in $(cat input_file)
do
some_command "$line"
done
< file
バックティックを配置すると、実際にはリダイレクトがまったく実行されませんcommand
。
command `< file`
動作しません。zsh は別の問題ですが、それはこの質問が扱っているシェルではありません)。
Hello World
1行に。最初に実行されsome_command Hello
、次にsome_command World
、またはではない ことがわかります。some_command "Hello World"
some_command Hello World
あなたはバックティックを使用してそれを行います:
echo World > file.txt
echo Hello `cat file.txt`
echo "Hello * Starry * World" > file.txt
、最初のステップで出力した場合、2つ目のコマンドに少なくとも4つの個別の引数が渡されます-おそらくさらに、*
sは現在のディレクトリにあるファイルの名前に展開されます。
fork()
には、stdoutに接続されたFIFOを使用してサブシェルをオフにし、/bin/cat
そのサブシェルの子として呼び出し、FIFOを介して出力を読み取ります。と比較して$(<file.txt)
、サブシェルやFIFOを使用せずにファイルの内容を直接bashに読み取ります。
可能なすべてのコマンドライン引数(スペースを含む値、改行を含む値、リテラル引用符を含む値、印刷できない値、グロブ文字を含む値など)に対して機能する堅牢な方法でこれを行う場合は、少し時間がかかりますもっと面白い。
引数の配列を指定してファイルに書き込むには:
printf '%s\0' "${arguments[@]}" >file
...と交換し"argument one"
、"argument two"
必要に応じて、など。
そのファイルから読み取り、その内容を使用するには(bash、ksh93、または配列を持つ別の最近のシェル):
declare -a args=()
while IFS='' read -r -d '' item; do
args+=( "$item" )
done <file
run_your_command "${args[@]}"
そのファイルから読み取り、その内容を使用するには(配列のないシェルで。これはローカルのコマンドライン引数リストを上書きするので、関数の引数を上書きするのではなく、関数の内部で行うのが最適です。グローバルリスト):
set --
while IFS='' read -r -d '' item; do
set -- "$@" "$item"
done <file
run_your_command "$@"
-d
(異なる行末デリミタの使用を許可する)は非POSIX拡張であり、配列のないシェルもそれをサポートしない場合があることに注意してください。その場合は、非シェル言語を使用して、NUL区切りのコンテンツをeval
-safe形式に変換する必要がある場合があります。
quoted_list() {
## Works with either Python 2.x or 3.x
python -c '
import sys, pipes, shlex
quote = pipes.quote if hasattr(pipes, "quote") else shlex.quote
print(" ".join([quote(s) for s in sys.stdin.read().split("\0")][:-1]))
'
}
eval "set -- $(quoted_list <file)"
run_your_command "$@"
コマンドの引数としてファイルの内容を渡す方法は次のとおりです。
./foo --bar "$(cat ./bar.txt)"
$(<bar.txt)
(適切な拡張子を持つbashなどのシェルを使用する場合)と同等です。$(<foo)
は特殊なケースです。で使用される通常のコマンド置換とは異なり、$(cat ...)
操作するためにサブシェルをforkしないため、かなりのオーバーヘッドが回避されます。
あなたがする必要があるすべてはarguments.txt
内容でファイルを回すことです
arg1
arg2
argN
my_command arg1 arg2 argN
あなたは、単に使用することができますxargs
:
xargs -a arguments.txt my_command
xargs
呼び出しに追加の静的引数を置くことができxargs -a arguments.txt my_command staticArg
ます。my_command staticArg arg1 arg2 argN
私のbashシェルでは、次のものが魅力のように機能しました:
cat input_file | xargs -I % sh -c 'command1 %; command2 %; command3 %;'
ここで、input_fileは
arg1
arg2
arg3
明らかなように、これにより、input_fileの各行で複数のコマンドを実行できます。これは、私がここで学んだ素晴らしいトリックです。
$(somecommand)
ある場合、そのコマンドはテキストとして渡されるのではなく実行されます。同様に、>/etc/passwd
リダイレクトや上書き/etc/passwd
(適切なアクセス許可で実行されている場合)などとして処理されます
xargs -d $'\n' sh -c 'for arg; do command1 "$arg"; command2 "arg"; command3 "arg"; done' _
入力ファイルの1行につき1つのシェルを開始するのではなく、可能な限り多くの引数を各シェルに渡すため、より効率的です。
@Wesley Riceの回答を2、3回編集した後、変更が大きくなりすぎて、自分で作成するのではなく、彼の回答を変更し続けることができないと判断しました。だから、私は自分で書く必要があると決めました!
ファイルの各行を読み取り、次のように1行ずつ操作します。
#!/bin/bash
input="/path/to/txt/file"
while IFS= read -r line
do
echo "$line"
done < "$input"
これは、作成者のVivek Giteから直接提供されています:https : //www.cyberciti.biz/faq/unix-howto-read-line-by-line-from-file/。彼は信用を得ます!
構文:読むバッシュのUnixとLinuxのシェル上の行毎にファイル:
1. bashの、kshの、zshのため構文は次のとおりであり、すべての他のシェル行毎にファイルを読み込む
2.while read -r line; do COMMAND; done < input.file
3.-r
オプションは、コマンドを読み取るために渡さバックスラッシュエスケープが解釈されないようにします。
4.IFS=
読み取りコマンドの前にオプションを追加して、先頭/末尾の空白が削除されないようにします
-5。while IFS= read -r line; do COMMAND_on $line; done < input.file
そして今私が持っていたこの今閉じた質問に答えるために:ファイルからファイルのリストを `git add`することは可能ですか?-これが私の答えです:
FILES_STAGED
は、各行が私がやりたいファイルへの相対パスである一連の行を含むファイルへの絶対パスを含む変数であることに注意してくださいgit add
。このコードスニペットは、このプロジェクトの「eRCaGuy_dotfiles / useful_scripts / sync_git_repo_to_build_machine.sh」ファイルの一部になり、開発中のファイルをあるPC(例:私がコーディングしたコンピューター)から別のPC(例:a私が構築するより強力なコンピューター):https : //github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles。
while IFS= read -r line
do
echo " git add \"$line\""
git add "$line"
done < "$FILES_STAGED"
git add
する方法:ファイルからファイルのリストを「git add」することはできますか?