xargsにスペースと猫からの特殊文字を処理させる方法は?


9

私が持っているfile名前のリストが含まれていることを。つまり:

Long Name One (001)
Long Name Two (201)
Long Name Three (123)
...

スペースといくつかの特殊文字。私はこれらの名前からディレクトリを作りたかった、すなわち:

cat file | xargs -l1 mkdir

それはすなわち、個々のディレクトリをスペースで区切っなりLongNameOneTwoThree、代わりの Long Name One (001)Long Name Two (201)Long Name Three (123)

どうやってやるの?

回答:


13

使用-d '\n'あなたとのxargsコマンドを実行します。

cat file | xargs -d '\n' -l1 mkdir

マンページから:

-d delim
              Input  items  are  terminated  by the specified character.  Quotes and backslash are not special; every
              character in the input is taken literally.  Disables the end-of-file string, which is treated like  any
              other  argument.   This can be used when the input consists of simply newline-separated items, although
              it is almost always better to design your program to use --null where this is possible.  The  specified
              delimiter  may be a single character, a C-style character escape such as \n, or an octal or hexadecimal
              escape code.  Octal and hexadecimal escape codes are understood as for the printf command.    Multibyte
              characters are not supported.

出力例:

$ ls
file

$ cat file
Long Name One (001)
Long Name Two (201)
Long Name Three (123)

$ cat file | xargs -d '\n' -l1 mkdir

$ ls -1
file
Long Name One (001)
Long Name Three (123)
Long Name Two (201)

-dオプションにはGNU xargsが必要です。
cuonglm 2016年

@cuonglm主にGNU xargsが見つかったと思います。私もチェックしました123。はいBSDがケースかもしれません
Pandya

6

xargs実装サポート-0オプションの場合:

tr '\n' '\0' <file | xargs -0 -l1 mkdir

POSIXly:

while IFS= read -r file; do
  mkdir -p -- "$file"
done <file

whileテキストを処理するためにループを使用することは、シェルスクリプトの悪い習慣と見なされたことに注意してください)


mkdirディレクトリごとに1 つ呼び出す必要はなくmkdir、複数の引数を取ることができることに注意してください。
ステファンChazelas

3

xargs は、引数が空白または改行で区切られる非常に特殊な入力形式(他の形式の垂直空白、現在のロケールに依存する場合がある)、および一重引用符、二重引用符、バックスラッシュを使用してそれらをエスケープできる(ただし、別の形式)シェル引用からの道)。

-l1は、1行の入力を1つの単一の引数としてに渡すのではなく、1行の入力ごとにmkdir1回のmkdir呼び出しを呼び出しますが、その行の単語は依然としてに異なる引数として分離されますmkdir

のGNU実装にはxargs-0NULで区切られた入力を受け入れるオプションが数十年前に追加されました。NUL文字はコマンドの引数またはファイル名(1行に1つのファイルを置く選択したリスト形式)に出現できない唯一の文字であるため、コマンドの引数となる単語を分離する最も明白な方法です。ファイル名に改行を使用できないため、すべての可能なファイル名を表すことはできません)。

これ-0は他のいくつかのxargs実装によってコピーされましたが、すべてではありません。

あなたができるもので:

<file tr '\n' '\0' | xargs -0 mkdir -p --

これはmkdir、できるだけ多くの引数を使用して、可能な限り数回呼び出します。

ただし、fileが空の場合mkdirでも実行されmkdir、引数がないために構文エラーが発生することに注意してください。GNU xargsは、-r他のいくつかの実装によってコピーされたオプションを追加しました。

GNUはxargsまた、(後で)-d任意の区切り文字を指定できるオプションを追加しましたが、他の実装がそれをコピーしたとは思いません。GNUのxargs場合、最善の方法は次のとおりです。

xargs -rd '\n' -a file mkdir -p --

-astdinの代わりに(これもGNU拡張機能で)ファイルを渡すと、mkdirのstdinが保持されます。

POSIXlyでは、入力を後処理して、が期待する形式にする必要がありますxargs。あなたはそれを例えば次のようにして行うことができます:

<file sed 's/"/"\\""/g; s/^/"/; s/$/"/' | xargs mkdir -p --

各行を二重引用符で囲み、xargsにフィードする前と"同じよう"\""にエスケープします。

ただし、考えられる制限に注意してください。

  • 上記のファイルが空の場合のエラー
  • sedのコンテンツがfile現在のロケールで有効なテキストでない場合、一部の実装(を含む)で失敗する可能性があります。file複数の異なる文字セット、またはロケールの文字セットとは異なる文字セットでエンコードされたファイル名が含まれている場合は、ロケールをCに修正すると便利です。
  • 一部のxargs実装では、引数の最大長に途方もなく低い制限があります(255バイトまで低くすることができます)。

空の入力エラーで構文エラーを回避するには、次のように記述します。

<file sed 's/"/"\\""/g; s/^/"/; s/$/"/' |
  xargs sh -c '[ "$#" -eq 0 ] || exec mkdir -p -- "$@"' sh

1

名前をnullで終了し、そこで分割します。

cat file | tr '\n' '\0' | xargs -l1 -0 mkdir

trcat出力する改行をに置き換え、\0-0フラグxargsはの引数を分割するように指示してい\0ます。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.