find
이 명령은 파일 이름을 null로 구분된 문자열( -print0
제공된 경우)로 출력할 수 있으며 옵션이 켜진 상태에서 사용할 수 있습니다 xargs
. -0
그러나 그 사이에는 해당 파일 모음을 조작하기가 어렵습니다. sort
명령에는 -z
파일을 정렬할 수 있는 스위치가 있지만 head
포함되지는 않습니다 tail
.
이러한 null로 구분된 입력을 편리한 방법으로 어떻게 head
AND 할 수 있습니까? tail
(언제든지 짧고 느린 Ruby 스크립트를 만들 수 있지만 더 좋은 방법이 있기를 바랍니다)
답변1
GNU head
및 tail
coreutils 버전 8.25부터 -z
옵션이 있습니다.
이전 버전이나 GNU가 아닌 시스템의 경우 다음 \0
과 같이 교체해 볼 수 있습니다 \n
.
find ... -print0 |
tr '\0\n' '\n\0' |
head |
tr '\0\n' '\n\0'
일부 head
구현에서는 NUL 문자를 처리할 수 없지만(POSIX에서는 이를 요구하지 않음) find는 처리하며 -print0
텍스트 head
유틸리티는 일반적으로 NUL 문자를 지원합니다.
tr
함수를 사용하여 두 s 사이의 명령을 래핑할 수도 있습니다 .
nul_terminated() {
tr '\0\n' '\n\0' | "$@" | tr '\0\n' '\n\0'
}
find ... -print0 | nul_terminated tail -n 12 | xargs -r0 ...
아래의 nul_terminated
a는 \0
개행 문자를 나타냅니다. 예를 들어 \n
다음으로 바꾸세요 _
.
find . -depth -name $'*\n*' -print0 | nul_terminated sed '
p;h;s,.*/,,;s/\x0/_/g;H;g;s,[^/]*\n,,' | xargs -r0n2 mv
( \x0
또한 GNU 확장).
여러 개를 실행해야 하는 경우필터명령을 사용하면 다음과 같이 할 수 있습니다.
find ... -print0 |
nul_terminated cmd1 |
nul_terminated cmd2 | xargs -r0 ...
그러나 이는 일부 중복 tr
명령을 실행하는 것을 의미합니다. 또는 다음을 실행할 수 있습니다.
find ... -print0 | nul_terminated eval 'cmd1 | cmd2' | xargs -r0 ...
답변2
이전 시스템에서는 null로 구분된 입력이 지원되었으므로 grep
3개의 최신 파일을 가져오는 대신 이 작업을 수행했습니다.head --zero-terminated -n 3
find . -maxdepth 1 -type f -printf "%T@ %p\0" | sort -zrn | grep -zm 3 ""
sort
와 의 조합을 사용하면 grep
대체를 통해 tail
세 번째 최신 파일을 얻을 수 있습니다.
find . -maxdepth 1 -type f -printf "%T@ %p\0" | sort -zrn | grep -zm 3 "" | sort -zn | grep -zm 1 ""
파일 이름만:
find . -maxdepth 1 -type f -printf "%T@ %p\0" | sort -zrn | grep -zm 3 "" | sort -zn | grep -zPom 1 "(?s)/.*"
불행하게도 -o
(일치만) 0으로 구분된 출력(버그!?)을 비활성화합니다. 이는 다음을 통해 활성화되고 -z
끝 줄 바꿈이 있는 파일 이름을 반환하므로 추가 파이핑을 허용하지 않습니다.
find . -maxdepth 1 -type f -printf "%T@ %p\0" | sort -zrn | grep -zm 3 "" | sort -zn | grep -zPom 1 "(?s)/.*" | xargs -0 ls -l
ls: cannot access /te
st
: No such file or directory
이 문제는 다음을 사용하여 해결할 수 있습니다 read
.
find . -mindepth 1 -maxdepth 1 -type f -printf "%T@ %p\0" | sort -zrn | grep -zm 3 "" | sort -zn | { IFS=" " read -rd '' mtime file && echo -en "$file\0"; } | xargs -0 -n1 ls -l
-rw-r--r-- 1 root root 0 Apr 24 17:46 ./te?st
( ls -t
예상대로 파일 이름의 개행 문자에 대해 물음표를 반환합니다.)
또는 현재 디렉터리에서 가장 오래된 100개 파일을 가져오는 방법에 대한 또 다른 예는 다음과 같습니다.
find /tmp/test -mindepth 1 -maxdepth 1 -type f -printf "%T@ %p\0" | sort -zn | grep -zm 10 "" | { while IFS=" " read -rd '' mtime file; do echo -en "$file\0"; done; } | xargs -0 -n1 ls -bl
-rw-r--r-- 1 root root 0 Mar 23 14:32 /tmp/test/foo\ baz.txt
-rw-r--r-- 1 root root 0 Apr 26 10:43 /tmp/test/foo\nbar\ baz.txt
...