사람이 읽을 수 있는 경로 목록을 다른 명령으로 리디렉션하는 방법은 무엇입니까?

사람이 읽을 수 있는 경로 목록을 다른 명령으로 리디렉션하는 방법은 무엇입니까?

locate"사람이 읽을 수 있는 형식"(즉, 선행 공백 없이)으로 경로 목록을 생성하는 명령 출력과 같은 명령 출력을 사용할 때 \출력을 다른 명령으로 리디렉션하려면 어떻게 해야 합니까?

의 출력에서는 $ locate [something]공백이 포함된 경로가 생성되므로 다른 프로그램에서 공백이 포함된 경로를 사용할 수 없습니다. 예를 들어, 내가

$ du -h `locate *.doc`

이렇게 하면 공백이 포함된 모든 파일과 디렉터리에 오류가 발생합니다. (공백으로 틱을 감싸는 것은 작동하지 않습니다)

답변1

그것을 사용하는 구체적인 이유는 무엇입니까 locate? 이는 귀하의 요구 사항을 충족하는 것 같습니다.

find . -type f -name '*doc' -exec du -h "{}" \;

즉, 만약 당신이진짜locate또는 같은 도구를 사용하고 그 입력을 다른 프로그램에 인수로 전달하려는 경우 일부 도구에서 제공하는 분리된 출력과 입력을 find활용할 수 있습니다 . 그리고 두 가지 모두 읽기용으로 설계된 보다 프로그래밍 방식으로 친숙한 출력을 얻을 수 있는 옵션( 's 및 's )이 있습니다.NULlocatefindlocate-0find-print0xargs그것은 -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과 같은 셸(zsh에서만 분할)에서 Split+glob을 호출합니다.

기본적으로 분할은 $IFS공백, 탭 및 줄 바꿈(zsh에서는 NUL)의 특수 매개변수가 포함된 문자에 대해 수행됩니다. 이는 공백 문자가 포함된 파일 이름에서 명령이 작동하지 않는 이유를 설명합니다.

다음을 수행할 수 있습니다.

(IFS='
' # split on newline only
set -o noglob # disable glob
du -hc -- $(locate '*.doc'))

그러나 파일 이름에 개행 문자가 포함되어 있으면 여전히 실패합니다. 출력을 locate전혀 사후 처리할 수 없습니다.

대부분의 구현에는 파일 경로를 구분하여 출력하는 옵션이 locate있습니다 . NUL은 파일 경로에 나타날 수 없는 유일한 바이트 값입니다. 즉, 출력이 사후 처리 가능함을 의미합니다. NUL로 분할하면 됩니다.-0NUL

존재하다 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[@]}"

여전히 두 가지 질문이 남습니다.

  1. locate파일이 발견 되지 않으면 du -hc --인수 없이 실행됩니다. 즉, 현재 작업 디렉터리의 디스크 사용량을 알려줍니다.
  2. 반면에 locate많은 파일이 발견되면 결국 시스템 호출 제한에 도달하여 execve()오류가 발생할 수 있습니다.인수 목록이 너무 깁니다.실수.

다음을 수행하면 이러한 문제를 모두 피할 수 있습니다.

locate -0 '*.doc' | xargs -r0 du -hc --

( -r그리고 -0GNU 구현의 비표준 확장 xargs과 마찬가지로 -hGNU 구현의 비표준 확장 입니다 du.)

그러나 이로 인해 새로운 문제가 발생합니다. 제한을 해결하기 위해 여러 번 xargs실행되지만 이는 몇 개의 행을 얻게 되며 여러 번 하드 링크된 파일의 디스크 사용량이 여러 번 계산될 수 있음을 의미합니다.duexecve()total

감사합니다 -r. 파일이 없으면 du실행되지 않습니다. 하지만 이는 한 줄도 표시되지 않는다는 의미이기도 합니다.locate0 total

최신 버전의 GNU를 사용하면 다음 du과 같은 방법으로 이러한 문제를 해결할 수 있습니다.

locate -0 '*.doc' | du --files0-from=- -hc

이번에는 매개변수 대신 파이프를 통해 파일 목록을 전달하므로 매개변수의 크기에는 제한이 없습니다. 이는 또한 목록을 저장하기 위해 많은 메모리를 할당할 필요가 없으며 출력을 시작 du하자마자 locate처리를 시작할 수 있음을 의미합니다.

관련 정보