xargs가 공백과 특수 문자를 처리하도록 만드는 방법은 무엇입니까?

xargs가 공백과 특수 문자를 처리하도록 만드는 방법은 무엇입니까?

file이름 목록이 포함된 목록이 있습니다 . 즉:

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

공백과 일부 특수 문자가 포함됩니다. 다음과 같은 이름으로 디렉터리를 만들고 싶습니다.

cat file | xargs -l1 mkdir

이는 디렉토리가 공백으로 구분되도록 합니다(예: Long, Name, 대신 , One, Two, , ) .ThreeLong 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

( while쉘 스크립트에서 텍스트를 처리하기 위해 루프를 사용하는 것은 나쁜 습관으로 간주됩니다.)

답변3

xargs매우 특별한 입력 형식이 필요합니다. 여기서 인수는 공백이나 개행(현재 로케일에 따라 다른 형태의 수직 공백)으로 구분되며 작은 따옴표, 큰 따옴표 및 백슬래시를 사용하여 이스케이프할 수 있습니다(그러나 쉘 따옴표와 다른 방식).

-l1입력 줄을 단일 인수로 전달하는 대신 각 입력 줄에 대해 호출이 이루어 mkdir지지만 mkdir해당 줄의 단어는 여전히 고유한 인수로 분리됩니다 mkdir.

수십 년 전의 GNU 구현에는 NUL로 구분된 입력을 허용하는 옵션이 xargs추가되었습니다 . -0이는 결국 명령 인수가 될 단어를 분리하는 가장 확실한 방법입니다. 왜냐하면 NUL 문자는 명령 인수나 파일 이름(선택한 목록 형식에서는 한 줄에 하나의 파일을 입력함)에 나타날 수 없는 유일한 문자이기 때문입니다. 파일 이름에 개행 문자를 허용하지 않기 때문에 가능한 모든 파일 이름을 나타냅니다.

이것은 -0여러 다른 구현에 의해 복사되었지만 xargs전부는 아닙니다.

이를 통해 다음을 수행할 수 있습니다.

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

mkdir이는 가능한 한 많은 인수를 사용하여 가능한 한 적은 횟수로 호출됩니다 .

그러나 file비어 있으면 계속 실행되며 mkdir매개변수 누락으로 인해 구문 오류가 발생합니다. mkdirGNU는 다른 구현에 의해 복사된 옵션을 xargs추가했습니다 .-r

GNU는 xargs(나중에) -d임의의 구분 기호를 지정할 수 있는 옵션도 추가했지만 다른 구현에서는 이를 복제할 수 없을 것 같습니다. GNU의 경우 xargs가장 좋은 접근 방식은 다음과 같습니다.

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

-astdin 대신 GNU 확장자를 사용하여 파일을 전달하면 mkdirstdin이 보존된다는 의미입니다.

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

관련 정보