Wie bringt man Xargs dazu, mit Leerzeichen und Sonderzeichen von Katzen umzugehen?

9

Ich habe eine file, die eine Liste von Namen enthält. dh:

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

mit Leerzeichen und einigen Sonderzeichen. Ich wollte aus diesen Namen Verzeichnisse machen, dh:

cat file | xargs -l1 mkdir

Es macht einzelne Verzeichnisse durch Leerzeichen getrennt, das heißt Long, Name, One, Two, Three, statt Long Name One (001), Long Name Two (201), Long Name Three (123).

Wie kann ich das machen?

Majal
quelle

Antworten:

13

Verwenden Sie -d '\n'mit Ihrem xargsBefehl:

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

Von der Manpage:

-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.

Beispielausgabe:

$ 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)
Pandya
quelle
Sie benötigen GNU xargs als -dOption.
Cuonglm
@ Cuonglm Ich denke, meistens GNU Xargs gefunden. Ich habe auch 1 , 2 , 3 überprüft . ja BSD kann der Fall sein
Pandya
6

Wenn Ihre xargs-Implementierungsunterstützungsoption -0:

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

POSIXly:

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

(Beachten Sie, dass die Verwendung von whileSchleife zum Verarbeiten von Text im Shell-Skript als schlechte Praxis angesehen wird.)

cuonglm
quelle
Beachten Sie, dass es nicht erforderlich ist, einen mkdirpro Verzeichnis aufzurufen, sondern mkdirmehr als ein Argument annehmen kann.
Stéphane Chazelas
2

xargs erwartet ein ganz besonderes Eingabeformat, bei dem Argumente durch Leerzeichen oder Zeilenumbrüche begrenzt werden (manchmal andere Formen vertikaler Leerzeichen, manchmal abhängig vom aktuellen Gebietsschema) und bei denen einfache Anführungszeichen, doppelte Anführungszeichen und Backslash verwendet werden können, um sie zu umgehen (jedoch in einem anderen Weg von Shell-Anführungszeichen).

-l1besteht nicht darin, eine Eingabezeile als ein einziges Argument an zu übergeben mkdir, sondern einen mkdirAufruf für jede einzelne Eingabezeile aufzurufen , wobei jedoch Wörter in dieser Zeile immer noch als unterschiedliche Argumente getrennt sind mkdir.

Die GNU-Implementierung hat vor Jahrzehnten xargseine -0Option hinzugefügt , um NUL-begrenzte Eingaben zu akzeptieren. Dies ist der naheliegendste Weg, um Wörter zu trennen, die letztendlich Argumente für einen Befehl sein werden, da das NUL-Zeichen zufällig das einzige Zeichen ist, das in einem Befehlsargument oder Dateinamen nicht vorkommen kann (das von Ihnen gewählte Listenformat, in das eine Datei pro Zeile eingefügt wird kann nicht alle möglichen Dateinamen darstellen, da kein Zeilenumbruch in einem Dateinamen zulässig ist.

Das -0wurde von mehreren anderen xargsImplementierungen kopiert , aber nicht von allen.

Mit denen können Sie tun:

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

Das wird mkdirso wenig wie möglich mit so vielen Argumenten wie möglich aufgerufen .

Beachten Sie jedoch, dass wenn filees leer ist, mkdires weiterhin ausgeführt wird und Sie mkdiraufgrund des fehlenden Arguments einen Syntaxfehler erhalten . GNU xargshat eine -rOption für die hinzugefügt , die von einigen anderen Implementierungen kopiert wurde.

GNU xargsfügte (später) auch eine -dOption hinzu , um beliebige Trennzeichen angeben zu können, aber ich glaube, keine andere Implementierung hat sie kopiert. Mit GNU xargsist der beste Weg mit:

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

Wenn Sie die Datei mit -a(auch einer GNU-Erweiterung) anstelle von stdin übergeben, mkdirbleibt das stdin erhalten.

POSIXly müssten Sie die Eingabe nachbearbeiten, um sie in das von erwartete Format zu bringen xargs. Sie könnten es zum Beispiel tun mit:

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

Wo wir jede Zeile in doppelte Anführungszeichen setzen und jede "wie "\""vor dem Füttern an xargs maskieren.

Beachten Sie jedoch mögliche Einschränkungen:

  • Der Fehler, wenn die Datei leer ist, wurde bereits oben erwähnt
  • Bei einigen Implementierungen (einschließlich von sed) kann dies fehlschlagen, wenn der Inhalt von fileim aktuellen Gebietsschema kein gültiger Text ist. Wenn fileDateinamen enthalten, die in mehr als einem anderen Zeichensatz oder einem anderen Zeichensatz als dem des Gebietsschemas codiert sind, können Sie das Gebietsschema auf C festlegen, was hilfreich sein sollte.
  • Einige xargsImplementierungen haben lächerlich niedrige Grenzen für die maximale Länge eines Arguments (kann bis zu 255 Byte betragen).

Um den Syntaxfehler bei einem leeren Eingabefehler zu umgehen, können Sie Folgendes schreiben:

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

Machen Sie die Namen nullterminiert und teilen Sie sie dort auf:

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

trersetzt die neue Zeile, durch die catausgegeben wird \0, und die -0Flags in weisen xargssie an, Argumente auf dem zu teilen \0.

Kira
quelle
1

Sie können dies POSIXLY mit der -IOption tun :

xargs -I % mkdir % < file

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

Steven Penny
quelle
Während es mit dem Beispiel des OP funktionieren würde, hätten Sie immer noch Probleme mit führenden Leerzeichen, einfachen Anführungszeichen, doppelten Anführungszeichen und umgekehrten Schrägstrichen (und möglicherweise langen Zeilen und Byte-Sequenzen, die keine gültigen Zeichen im Gebietsschema bilden).
Stéphane Chazelas