단일 명령으로 하위 디렉터리에서 파일을 찾고 파일 이름별로 정렬하는 방법은 무엇입니까?

단일 명령으로 하위 디렉터리에서 파일을 찾고 파일 이름별로 정렬하는 방법은 무엇입니까?

일반 조회를 사용한 결과 find . ! -path "./build*" -name "*.txt":

./tool/001-sub.txt
./tool/000-main.txt
./zo/001-int.txt
./zo/id/002-and.txt
./as/002-mod.txt

정렬할 때 sort -n:

./as/002-mod.txt
./tool/000-main.txt
./tool/001-sub.txt
./zo/001-int.txt
./zo/id/002-and.txt

그러나 원하는 출력은 다음과 같습니다.

./tool/000-main.txt
./zo/001-int.txt
./tool/001-sub.txt
./zo/id/002-and.txt
./as/002-mod.txt

이는 출력이 다음을 기반으로 함을 의미합니다.파일 이름만, 그러나 폴더 정보는 출력의 일부로 유지되어야 합니다.

편집하다: 하위 디렉터리 구조에 여러 수준이 포함될 수 있으므로 예제가 더 복잡해집니다.

답변1

마지막 필드(필드 구분 기호로 간주)를 기준으로 정렬해야 합니다 /. 아쉽게도 필드 수가 변경될 때( sort -k음수 값만 취할 수 있는 경우) 이를 수행할 수 있는 도구가 생각나지 않습니다 .

이 문제를 해결하려면 장식-정렬-장식 취소를 수행해야 합니다. 즉, 파일 이름을 가져와서 시작 부분에 넣은 다음 필드 구분 기호를 붙인 다음 정렬하고 첫 번째 열과 필드 구분 기호를 제거합니다.

find . ! -path "./build*" -name "*.txt" |\
    awk -vFS=/ -vOFS=/ '{ print $NF,$0 }' |\
    sort -n -t / |\
    cut -f2- -d/

awk명령은 다음을 의미합니다.필드 구분 기호 FS로 설정됩니다 /. 이는 필드를 읽는 방법에 영향을 줍니다. 이것출력 필드 구분 기호 OFS또한 /;로 설정하면 레코드 인쇄 방법에 영향을 미칩니다. 다음 명령문은 마지막 열( NF레코드의 필드 수이므로 마지막 필드의 인덱스이기도 함)과 전체 레코드( $0전체 레코드)를 인쇄하라고 말합니다. 그 사이에 OFS를 추가하세요. 그런 다음 목록이 sort편집되고 /필드 구분 기호로 처리됩니다. 레코드에서 파일 이름이 먼저 있으므로 그에 따라 정렬됩니다. 그런 다음 cut필드 2를 끝까지 인쇄하고 다시 /필드 구분 기호로 처리합니다.

답변2

"-printf" 파일을 사용하여 이름과 경로를 출력하고, 이름별로 정렬하고, 마지막 단계에서 이름을 자릅니다. "###"은 자르기를 돕기 위한 표시일 뿐입니다.

find -name "*.txt" -printf "%f###%p\n" | sort -n | sed 's/.*###//'

%f는 파일 이름을 인쇄하고, %p는 전체 경로를 인쇄합니다.

find 명령을 단순화하여 한 줄로 만들었습니다. 물론 이 부분은 그대로 두십시오 ! -path "./build*".

답변3

zsh ≥4.3.10에서:

print -l -- **/*.txt~build*(oe\''REPLY=${REPLY:t}'\')
  • **/*.txt*.txt현재 디렉터리 및 해당 하위 디렉터리와 일치합니다 .재귀적으로.
  • ~build* 들어오지 못하게 하다build*텍스트가 (like )로 ! -path './build*'시작하는 콘텐츠 와 일치합니다 . ( setopt extended_glob먼저 필요합니다.)
  • (oe\''…'\')정렬이다글로벌 예선. REPLY=…반환될 문자열에서 정렬할 문자열을 구성합니다.
  • ${REPLY:t}~이다기본 이름("꼬리") 경로입니다.

관련 정보