ファイル名に依存するフラグ引数を使用して、各ファイルに対してコマンドを実行します。

ファイル名に依存するフラグ引数を使用して、各ファイルに対してコマンドを実行します。

次の名前のファイルを含むフォルダがあるとします。

file1.txt
file2.txt
file2.txt

など。次のようにそれぞれに対してコマンドを実行したいと思います。

mycommand file1.txt -o file1-processed.txt
mycommand file2.txt -o file2-processed.txt
mycommand file3.txt -o file3-processed.txt

など。

-processedこのサイトにはいくつかの同様の質問があります。違いは、拡張子の前のファイル名の途中にテストを挿入したいことです。

find作業のためのツールになりそうです。旗なしでも-oできます

find *.txt -exec mycommand "{}" ";"

ただし、{}構文はなどのように完全なファイル名を提供するため、ファイル名と拡張子の間に ""を追加することfile1.txtはできません。-processed単純なbashループを使用するとfor同様の問題があります。

これを行う簡単な方法はありますかfind

答え1

処理するすべてのファイルが同じフォルダにある場合は必要ではなく、デフォルトのシェルfindワイルドカードを使用できます。

for foo in *.txt ; do
  mycommand "${foo}" -o "${foo%.txt}-processed.txt"
done

シェルイディオムは、パターン${foo%bar}(この場合は拡張子)に一致する最小のサフィックス文字列を値から削除するため、必要なサフィックスに置き換えることができます。barfoo.txt

答え2

さまざまなシステムで実行されるスクリプトを作成し、移植性を念頭に置いている場合は、繰り返して起動するのとfor同じ${var%sfx}くらい良いことはありません。ユーザー 1404316答え。

しかし、自分のシステムで同様の作業を実行する便利な方法を探している場合は、心からお勧めします。GNUパラレル、これは基本的にxargsステロイドです。特定のタスクの解決策は次のとおりです。

parallel mycommand {} -o {.}-processed.txt ::: *.txt

次に、文字列リスト:::(シェルが*.txt一致するファイル名のリストに展開されます)を取得し、各文字列に対して実行して、mycommand {} -o {.}-processed.txt入力文字列{}(たとえばxargs)と{.}拡張子のないファイル名を変更します。

stdin(これでこれを行うことができます。パラメータfind-way)、またはとペアになりますが、拡張グローブ以外はlocateほとんど必要ありません。zsh

見てGNUパラレルチュートリアルそれができることを学びましょう。バッチ変換、サブディレクトリへのアーカイブ抽出などに常に使用します。

答え3

これは適応するユーザー1404316の回答アクションfind:

find . -type f -name '*.txt' \
   -exec sh -c 'for file do mycommand "$file" -o "${file%.txt}-processed.txt"; done' sh {} +

(すべての内容を1行に入力できます。省略してください。\読みやすくするために2行に分けてください。)


読みやすくするために書式設定する別の方法で埋め込まれたシェルスクリプトをより明確にします。

find . -type f -name '*.txt' -exec sh -c '
  for file
  do
    mycommand "$file" -o "${file%.txt}-processed.txt";
  done
' sh {} +

デフォルトでは、名前のないシェルスクリプトを生成します。

for file
do
    mycommand "$file" -o "${file%.txt}-processed.txt"
done

(二重引用符の間の文字列、拡張)すべてのファイル名を引数として'…'command() としてシェルに渡します。 (一般的に引用は不要で、中括弧を使用しません。)sh -c.txt{}"$file"

答え4

再帰およびより複雑な文字列置換が必要な場合findsedおよび組み合わせが機能する可能性があります。xargs

find . -iname '*.txt' -printf "%p\0-o\0%p\0" | sed -z '3~3s/\.txt$/-processed&/' | xargs -0 -n 3 echo mycommand

例:

$ find
.
./bar baz.txt
./foo.txt
$ find . -iname '*.txt' -printf "%p\0-o\0%p\0" | sed -z '3~3s/\.txt$/-processed&/' | xargs -0 -n 3 echo mycommand
mycommand ./bar baz.txt -o ./bar baz-processed.txt
mycommand ./foo.txt -o ./foo-processed.txt

このコマンドは-printf "%p\0-o\0%p\0"ファイルパスを-oASCII NUL文字で区切って2回印刷し、3行目の末尾の行に1つを挿入しますsed。次に、一度に3つの引数(ファイル名と編集されたファイル名)を使用してコマンドを実行します。-processed.txtxargs-o

関連情報