나는 순진한 노력을 기울이고 있습니다.
$ cat * | sort -u > /tmp/bla.txt
실패:
-bash: /bin/cat: Argument list too long
따라서 (거대한 임시 파일 생성)과 같은 어리석은 솔루션을 피하려면 다음을 수행하십시오.
$ find . -type f -exec cat {} >> /tmp/unsorted.txt \;
$ cat /tmp/unsorted.txt | sort -u > /tmp/bla.txt
다음을 사용하여 파일을 하나씩 처리할 수 있습니다(이렇게 하면 메모리 소비가 줄어들고 스트리밍 메커니즘에 더 가까워집니다).
$ cat proc.sh
#!/bin/sh
old=/tmp/old.txt
tmp=/tmp/tmp.txt
cat $old "$1" | sort -u > $tmp
mv $tmp $old
다음은 다음과 같습니다.
$ touch /tmp/old.txt
$ find . -type f -exec /tmp/proc.sh {} \;
더 간단하고 유닉스 스타일의 대안이 있습니까? cat * | sort -u
파일 수에 도달했을 때 MAX_ARG
? 이러한 일반적인 작업을 위해 작은 쉘 스크립트를 작성하는 것은 어색합니다.
답변1
최소한 Bash에서는 작동하는 간단한 수정입니다. printf
내장되어 있고 명령줄 인수 제한이 적용되지 않기 때문입니다.
printf "%s\0" * | xargs -0 cat | sort -u > /tmp/bla.txt
( echo * | xargs
공백 등이 포함된 파일 이름을 처리하는 것을 제외하고도 작동합니다.)
답변2
GNU sort
및 내장 셸 사용 printf
(현재 일부 변형을 제외한 모든 POSIX 유사 셸 pdksh
):
printf '%s\0' * | sort -u --files0-from=- > output
이제 한 가지 문제는 이 파이프라인의 두 구성 요소가 동시에 독립적으로 실행되기 때문에 왼쪽 구성 요소가 glob을 확장할 때 *
오른쪽 구성 요소가 이미 output
파일을 생성했을 수 있다는 것 입니다 -u
. output
입력 파일은 출력 파일이므로 출력을 다른 디렉터리( > ../output
예:)로 이동하거나 glob이 출력 파일과 일치하지 않는지 확인해야 할 수 있습니다.
이 경우 문제를 해결하는 또 다른 방법은 다음과 같이 작성하는 것입니다.
printf '%s\0' * | sort -u --files0-from=- -o output
이렇게 하면 쓰기용으로 sort
열리지만 output
(내 테스트에서는) 전체 파일 목록을 수신할 때까지(글로브가 확장된 후 오랜 시간이 흐른 후) 작동하지 않습니다. output
또한 읽을 수 있는 입력 파일이 없는 경우에도 손상을 방지합니다.
그것을 쓰는 또 다른 방법은 zsh
or로 쓰는 것 입니다.bash
sort -u --files0-from=<(printf '%s\0' *) -o output
이는 프로세스 대체를 사용하여 수행됩니다(여기서 <(...)
대체는 printf
기록되는 파이프의 읽기 끝을 참조하는 파일 경로로 대체됩니다). 이 함수는 ksh
에서 왔지만 ksh
개별 인수를 <(...)
명령으로 확장해야 하므로 구문과 함께 사용할 수 없습니다 --option=<(...)
. 그러나 다음 구문을 사용할 수 있습니다.
sort -u --files0-from <(printf '%s\0' *) -o output
cat
파일이 줄 바꿈으로 끝나지 않으면 파일에 제공된 출력에 대한 다른 접근 방식을 볼 수 있습니다.
$ printf a > a
$ printf b > b
$ printf '%s\0' a b | sort -u --files0-from=-
a
b
$ printf '%s\0' a b | xargs -r0 cat | sort -u
ab
또한 sort
정렬은 로케일( )의 데이터 정렬 알고리즘을 사용하여 수행되며 strcollate()
바이트 sort -u
수준의 고유 행이 아닌 해당 알고리즘으로 정렬된 각 행 집합 중 하나를 보고합니다. 바이트 수준에서 고유한 행에만 관심이 있고 정렬 순서에 대해서는 크게 신경 쓰지 않는 경우 정렬이 바이트 값을 기반으로 하는 C로 로케일을 수정하는 것이 좋습니다( memcmp()
; 이렇게 하면 속도가 빨라질 수 있습니다. 상황이 크게 개선되었습니다):
printf '%s\0' * | LC_ALL=C sort -u --files0-from=- -o output
답변3
find . -maxdepth 1 -type f ! -name ".*" -exec cat {} + | sort -u -o /path/to/sorted.txt
이렇게 하면 현재 디렉토리에서 숨겨지지 않은 모든 일반 파일을 연결하고 결합된 내용을 (중복 줄을 제거하면서) 파일로 정렬합니다 /path/to/sorted.txt
.
답변4
@ilkkachu와 비슷하지만 cat(1)은 필요하지 않습니다.
printf "%s\0" * | xargs -0 sort -u
또한 데이터가 매우 긴 경우 sort(1) 옵션을 사용하는 것이 좋습니다. - 평행선=질소
언제질소컴퓨터의 CPU 수입니다.