xargs를 결합하여 "ls -1"을 따옴표로 인쇄하려면 어떻게 해야 합니까?

xargs를 결합하여 "ls -1"을 따옴표로 인쇄하려면 어떻게 해야 합니까?

ls여러 디렉터리를 나열하려면 이와 같은 명령을 실행합니다 . 폴더의 빈 공간을 확인하십시오 X y.

ls -1d 2021*/"X y"/foobar

출력은 다음과 같습니다

'20211121-161518-801/X y/foobar'
'20211128-151513-585/X y/foobar'
'20211130-170001-724/X y/foobar'

ls는 여기서 여전히 따옴표를 사용하는 것 같습니다. 하지만 이 출력을 따옴표와 xargs결합 하면 이음새가 손실됩니다.

ls: Zugriff auf '20211121-161518-801/X' nicht möglich: Datei oder Verzeichnis nicht gefunden
ls: Zugriff auf 'y/foobar' nicht möglich: Datei oder Verzeichnis nicht gefunden

xargs 명령은 다음과 같습니다

ls -1d 2021*/"X y"/foobar | xargs ls

결국 나는 a를 사용하겠지만 xargs rm -rf이것은 xargs ls단지 테스트일 뿐이다.

답변1

Stéphane Chazelas는 "현대"에 대해 일반적으로 훌륭하고 심층적인 탐구를 제공하지만 ls모든 lses가 동일하게 만들어지는 것은 아닙니다. 새로운 GNU가 ls나오 더라도 --zero모든 곳에 퍼지는 데는 수십 년이 걸릴 것이며 여전히 모든 시스템, 특히 GNU 기반이 아닌 시스템에서는 작동하지 않을 것입니다.

일반적인 합의는 ls이것이 인간이 소비하기 위한 것이며 실제로 다른 목적으로 신뢰해서는 안 된다는 것입니다.

이것은 이전 관리자들 사이에서는 상당히 상식이지만, Linux가 틈새 시장을 넘어 점차 주류 및 국가화 환경으로 이동함에 따라 신규 및 초보 관리자는 여전히 많은 이해할 수 있는(또는 설명할 수 없는) 이유로 신규 및 초보 관리자만 사용 합니다 ls. ls(당신의 상황에서 알 수 있듯이) 심각한 문제가 됩니다. 이것이 바로 GNU가 수십 년 동안 "빠르게" 발전하고 있으며 누구에게나 선택 사항이 되어야 하는 이유입니다 ls.ls

그러나 이 문제를 즉각적이고 안정적이며 안전하게 해결하고 작업을 올바르게 수행하려면 find0으로 구분된 목록 생성기 또는 직접 명령 실행기로서 올바른 도구가 명령입니다.

find0으로 구분된 목록 생성기 로 사용됩니다 .

find topdir -mindepth 1 [-maxdepth 2] -type d -print0 | xargs -0 -I@ stat @

find직접 실행자로 사용:

find topdir -mindepth 1 [-maxdepth 2] -type d -exec stat '{}' \;

-mindpeth/를 사용하면 -maxdepth드롭 깊이를 제어 find하고 -type처리할 개체를 제어할 수 있습니다. 개체 이름이나 개체 경로도 일치시킬 수도 있습니다. 객체 이름은 기본적으로 "지능적인" 방식으로 손상되거나 이스케이프되지 않기 때문에 find두려움 없이 파이프(생성기)를 통해 또는 argv 벡터(실행기)의 일부로 이러한 항목을 원본 객체에 전달할 수 있습니다.

이런 방식으로 목록을 파이핑할 때는 -print0항상 이름이 0으로 구분되고 다른 문자(예: 공백 및 줄 바꿈)가 직접 표현될 수 있도록 하여 독자가 혼동하지 않도록 해야 한다는 점을 기억하세요.

답변2

GNU 구현에는 인용 스타일을 지정할 수 있는 옵션이 ls있지만 --quoting-style그 중 어느 것도 원하는 인용 스타일과 호환되지 않습니다 xargs.

xargs(1970년대 후반 PWB Unix에 의해 도입됨) 인용 스타일은 Bourne 쉘의 전신인 Mashey 쉘(PWB Unix에서도 유래)과 유사합니다.

ls --quoting-style=shell-always인용은 Bourne/POSIX 셸 스타일에서 수행되며, 작은따옴표 자체는 백슬래시 외에도 로 입력되고 지원 \'되지만 xargs인용 된 문자열에는 백슬래시로만 이스케이프할 수 있는 개행 문자가 포함될 수 없습니다.'...'"..."

POSIX xargs사양에서는 xargs입력이 현재 로케일의 텍스트로 구문 분석될 것으로 예상하며 256바이트보다 큰 인수에 대한 작동도 보장되지 않으므로 일반적으로 임의의 데이터를 처리하는 데 사용할 수 없습니다.

실제로 이를 사용하는 유일하고 신뢰할 수 있는 방법은 GNU(보통 비표준으로 사용하려는 ) 와 같은 일부 구현에서 옵션을 xargs사용하는 것입니다 .-0xargs-r

GNU의 다음 버전에는 NUL로 구분된 파일을 출력하는 옵션이 ls있으므로 --zero다음을 수행할 수 있습니다:

ls -t --zero | xargs -r0 printf ' * %s\n'

예를 들어.

이제 할 수 있는 일은 --quoting-style=shell-always패턴을 사용하여 해당 목록을 셸에 전달한 다음 NUL로 구분된 목록으로 변환하는 것입니다.

(
   echo 'files=('
   ls --quoting-style=shell-always -t
   echo '); print -rNC1 -- $files'
) | zsh | xargs -r0 some command

하지만 이미 사용하고 있다면 zsh꼭 그럴 필요는 없습니다. ls파일 메타데이터를 검색하는 기능이 내장 되어 있는 등 다른 기준에 따라 전역적으로 정렬 xargs할 수도 있습니다 (이 기능을 사용하려는 유일한 이유 ) . 그리고 그 자신의 순서.zshlsstatlszargs

어쨌든, 다음에서

ls -d -- *.txt

*.txt일치하는 파일 목록으로 확장되는 쉘입니다. ls그냥 인쇄하면 되기 때문에 매우 쓸모가 없습니다.

print내장된 NUL로 구분된 목록을 인쇄하는 항목에 glob 확장을 전달할 수도 있습니다 zsh.

print -rNC1 -- *.txt(N)

(ullglob 한정자는 여기서도 사용되므로 Nglob이 어떤 파일과도 일치하지 않으면 아무 것도 인쇄하지 않습니다.)

또는 bash셸에서(GNU 셸이기 때문에 GNU 시스템에서 여전히 사용되는 경우도 있음):

print0() {
  [ "$#" -eq 0 ] || printf '%s\0' "$@"
}
shopt -s nullglob
print0 *.txt

관련 정보