web-dev-qa-db-ja.com

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

名前のリストを含むfileがあります。例:

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

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

cat file | xargs -l1 mkdir

スペースで区切られた個々のディレクトリを作成します。つまり、Long Name One (001)Long Name Two (201)Long Name Three (123)

どうやってやるの?

9
Majal

使用する - -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)
13
Pandya

Xargs実装が-0オプションをサポートしている場合:

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

POSIXly:

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

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

6
cuonglm

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

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

GNU xargsの実装)は、NUL区切りの入力を受け入れるために-0オプションを数十年前に追加しました。これは、最終的に単語を分離する最も明白な方法です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 --

Stdinの代わりに-a(= 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
2

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

_cat file | tr '\n' '\0' | xargs -l1 -0 mkdir
_

trは、catが出力する改行を_\0_で置き換え、xargsの_-0_フラグは、_\0_。

1
Kira

あなたはこれをPOSIXLY -Iオプション:

xargs -I % mkdir % < file

http://pubs.opengroup.org/onlinepubs/9699919799/utilities/xargs.html

1
Steven Penny