
"사람이 읽을 수 있는 형식"(예 : 공백 locate
없이)으로 경로 목록을 생성하는 것과 같은 명령 출력으로 작업할 때 해당 출력을 다른 명령으로 어떻게 리디렉션합니까?\
의 출력은 $ locate [something]
공백이 포함된 경로를 생성하므로 공백이 포함된 경우 다른 프로그램에서 해당 경로를 사용할 수 없습니다. 예를 들어, 내가
$ du -h `locate *.doc`
이렇게 하면 공백이 포함된 모든 파일과 디렉터리에 오류가 발생합니다. (틱을 공백으로 감싸는 것은 작동하지 않습니다)
답변1
을 사용하는 구체적인 이유는 무엇입니까 locate
? 이는 귀하가 요청한 작업을 수행하는 것으로 보입니다.
find . -type f -name '*doc' -exec du -h "{}" \;
즉, 만약 당신이정말locate
또는 같은 도구를 사용하고 그 입력을 다른 프로그램에 매개변수로 전달하고 싶다면 일부 도구가 제공하는 구분된 출력과 입력을 find
활용할 수 있습니다 . 둘 다 프로그래밍 방식 으로 더 친숙한 출력을 얻을 수 있는 옵션( 's 및 's )이 있습니다.NUL
locate
find
locate
-0
find
-print0
xargs
그것은 -0
논쟁:
find . -type f -name '*doc' -print0 | xargs -0 du -h
locate -0 '*doc' | xargs -0 du -h
답변2
동일한 줄을 여러 명령에 전달하고 싶거나 전달해야 하는 경우 다음과 같이 작동합니다.
#!/usr/bin/env bash
T="${IFS}" # Save off the Internal Field Separator
IFS=$'\n' # Set it to newline.
while read file_line
do
echo "--"
echo "${file_line}"
echo "--"
done <<< $(locate $1)
IFS="${T} # Set it back to the original IFS.
포장해가는 것도 좋을 것 같아요어느""에 공백이 있을 수 있는 변수입니다.
답변3
명령 대체( $(...)
또는 `...`
구식 형식)를 따옴표로 묶지 않으면 Bourne과 같은 쉘에서 Split+glob(zsh에서만 분할)이 호출됩니다.
분할은 $IFS
기본적으로 공백, 탭 및 줄 바꿈(zsh에서는 NUL)을 포함하는 특수 매개변수의 문자에 대해 수행됩니다. 이는 공백 문자가 포함된 파일 이름에 대해 명령이 작동하지 않는 이유를 설명합니다.
당신은 할 수 있습니다 :
(IFS='
' # split on newline only
set -o noglob # disable glob
du -hc -- $(locate '*.doc'))
그러나 개행 문자가 포함된 파일 이름이 있으면 여전히 실패합니다. 의 출력은 locate
단순히 사후 처리가 불가능합니다.
대부분의 구현에는 파일 경로를 구분하여 출력하는 옵션이 locate
있습니다 . NUL은 파일 경로에서 발생할 수 없는 유일한 바이트 값입니다. 즉, 출력이 사후 처리 가능함을 의미합니다. NUL로 분할하면 됩니다.-0
NUL
안에 zsh
:
IFS=$'\0'
du -hc -- $(locate -0 '*.doc')
또는 명시적인 NUL 분할 연산자를 사용하는 것이 더 좋습니다.
du -hc -- ${(0)"$(locate -0 '*.doc')"}
4.4+ 에서는 bash
다음과 같을 수 있습니다.
readarray -td '' files < <(locate -0 '*.doc')
du -hc -- "${files[@]}"
그래도 여전히 두 가지 문제가 남아 있습니다.
locate
파일을 찾지 못하면 인수du -hc --
없이 실행됩니다. 즉, 현재 작업 디렉터리의 디스크 사용량을 알려줍니다.- 반면에 많은 파일을 찾으면 시스템 호출
locate
의 한계에 도달하여 결과를 얻을 수 있습니다 .execve()
인수 목록이 너무 깁니다.오류.
다음을 수행하면 두 가지 문제를 모두 피할 수 있습니다.
locate -0 '*.doc' | xargs -r0 du -hc --
( -r
그리고 -0
GNU 구현의 비표준 확장인 것은 xargs
GNU -h
구현의 비표준 확장입니다 du
).
그러나 이로 인해 새로운 문제가 발생합니다. 제한 을 해결하기 위해 여러 번 xargs
실행되지만 이는 여러 줄을 얻게 되며 여러 번 하드 연결된 파일의 디스크 사용량이 여러 번 계산될 수 있음을 의미합니다.du
execve()
total
덕분에 -r
파일 을 찾지 못하면 du
실행되지 않지만 locate
이는 또한 줄을 얻지 못할 것임을 의미합니다 0 total
.
최신 버전의 GNU에서는 du
이러한 문제를 다음과 같이 해결할 수 있습니다.
locate -0 '*.doc' | du --files0-from=- -hc
이번에는 파일 목록이 인수 대신 파이프를 통해 전달되므로 인수 크기에 제한이 없습니다. 이는 또한 해당 목록을 저장하기 위해 많은 양의 메모리를 할당할 필요가 없으며 출력을 시작 du
하자마자 작업을 시작할 수 있음 을 의미합니다.locate