file
名前のリストを含むリストがあります。つまり:
Long Name One (001)
Long Name Two (201)
Long Name Three (123)
...
スペースといくつかの特殊文字が含まれています。次の名前でディレクトリを作成したいと思います。
cat file | xargs -l1 mkdir
これにより、ディレクトリがスペースで区切られます(たとえば、、、Long
代わりName
に One
、、、、、Two
など)。Three
Long Name One (001)
Long Name Two (201)
Long Name Three (123)
どうすればいいですか?
答え1
使用-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)
答え2
xargsの実装が-0
オプションをサポートしている場合:
tr '\n' '\0' <file | xargs -0 -l1 mkdir
POSIX的に:
while IFS= read -r file; do
mkdir -p -- "$file"
done <file
答え3
xargs
非常に特別な入力フォーマットが必要です。ここでは、引数はスペースまたは改行(現在のロケールによって異なる形式の垂直スペース)で区切られ、単一引用符、二重引用符、およびバックスラッシュを使用してエスケープできます(ただしシェル引用符とは異なる方法)。
-l1
入力行を単一の引数として渡すのではなく、各入力行に対して呼び出しが行われますが、その行mkdir
のmkdir
単語はまだ一意の引数に分割されますmkdir
。
数十年前のGNU実装には、NULで区切られた入力を許可するオプションがxargs
追加されました。-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 --
-a
stdinの代わりに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
答え4
次のオプションを使用して、POSIXLYでこれを実行できます-I
。
xargs -I % mkdir % < file
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/xargs.html