Bash를 사용하여 지정된 디렉터리와 해당 하위 트리의 파일 이름, 해당 디렉터리에 생성된 마지막 파일의 생성 날짜 및 생성 시간을 찾고 싶습니다. 예를 들어 출력은 다음과 같습니다.
/home/dir filename0 creation_date0 creation_time0
/home/dir/subdir1 filename1 creation_date1 creation_time1
/home/dir/subdir2 filename2 creation_date2 creation_time2
답변1
노력하다:
$ find /path/to/dir -type d -print0 | xargs -0 -I{} bash -c '
path="{}";
ls -oAF --time=ctime --time-style=+"%Y-%m-%d %H:%M:%S" -t "$path" | \
awk -v dir="$path" '\''BEGIN {found=0} ($1 ~ /-[rwx-]{9}/ && found == 0) {printf "%s\t%s\t%s\t%s\n", dir, $7, $5, $6; found=1}'\'';'
탭으로 구분된 "absolute_path", "filename", "last_modif_date", "last_modif_time"을 사용한 출력 예:
/path/to/dir/otp_src_19.1/lib/ic/src icparse.erl 2016-09-20 21:56:21
/path/to/dir/otp_src_19.1/lib/dialyzer AUTHORS 2016-09-20 21:11:23
/path/to/dir/otp_src_19.1/lib/dialyzer/doc about.txt 2016-09-20 21:11:23
리뷰 2개:
- 위의 해결 방법은 최신 "생성" 또는 "생성" 날짜/시간이 아닌 최신 파일 상태 수정 날짜/시간을 기반으로 합니다. 생성 날짜/시간을 기준으로 파일을 구별하려면 다음이 필요합니다(확장된 속성)이 시스템에서 활성화되었습니다. 표준 문제(POSIX)가 아니기 때문에 이를 수행하지 않는다고 가정합니다. 따라서 이러한 메타데이터에 의존하면 이식성 문제가 발생할 수 있습니다.
활성화한 경우xattr
OP를 편집하여 이 솔루션을 업데이트할 수 있도록 명확하게 하고 알려 주시기 바랍니다. zsh
제안된 솔루션은 아마도 shell 을 사용하는 것 보다 간단할 것입니다bash
.bash
(zsh
와는 달리ls *(.)
) 목록 에서만일반 파일에서는 불가능합니다ls
. 즉, 다음을 수행하는 플래그나 옵션 또는 특수 글로빙 패턴이 없습니다ls --regular-file-only
. 따라서 파일을 나열하면ls [options]
일반 파일, 링크 및 디렉터리가 생성되며$PWD
일반 파일은 이들에서 필터링되어야 합니다.
작동 방식:
find /path/to/dir -type d -print0
로 시작하는 디렉토리의 하위 트리에서 모든 디렉토리를 찾습니다/path/to/dir
. 디렉토리 이름의 공백 문제를 방지하기 위해 표준 줄 끝 문자를 NULL로 대체하여 각 디렉토리를 인쇄합니다. 이는 다음으로 파이프됩니다.xargs -0 -I{} bash -c '...'
표준 입력(여기서 표준 입력은 파이프 입력 데이터로 대체됨)에서 들어오는 결과를 읽고 이를 다음 미니 Bash 스크립트에 표시합니다.ls -oAF --time=ctime --time-style=+"%Y-%m-%d %H:%M:%S" -t "$path" |
-AF
"거의 모든"( ) 파일을 긴 형식으로 나열하고 그룹(-o
) 정보 없이 전달된 디렉토리의 파일 유형에 관계없이 다음을 수행$path
합니다.--time-style=+"%Y-%m-%d %H:%M:%S"
마지막 디렉터리 상태 수정 날짜/시간을 다음 단계( )에서 쉽게 구문 분석할 수 있도록 나열된 파일 출력( )의 형식을 지정합니다 .--time=ctime
파일의 디렉터리 상태 수정 시간은 파일 자체의 수정 시간과 다를 수 있습니다.- 표시된 수정 시간( )을 기준으로 최신 항목부터
-t
파일을 정렬합니다 . - 파이프 형식 및 정렬된 출력을 다음
awk
필터로 보냅니다.
awk -v dir="$path" '...'
$path
내부awk
변수 에 값을 할당합니다.dir
BEGIN {found=0}
블록에서 표시 플래그를found
0으로 설정BEGIN
($1 ~ /-[rwx-]{9}/ && found == 0)
각 레코드에 대해 파일이 일반 파일인지 테스트합니다. 이 경우 레코드의 첫 번째 필드($1
)가 정규 표현식과 일치해야 하며-[rwx-]{9}
, (&&
) 해당 디렉터리에 대해 이러한 일이 적어도 한 번 발생했는지 여부( ) 한 번,$path
이 이 경우 show-flag(found
)는 더 이상 0이 아니며 레코드를 건너뛰고 아무런 조치도 취하지 않습니다.{printf "%s\t%s\t%s\t%s\n", dir, $7, $5, $6; found=1}
이 블록은 레코드를 건너뛰지 않는 한 실행됩니다. 즉, 파일은 일반 파일이고$path
현재 처리 중인 디렉터리( )에 표시되는 첫 번째 파일입니다. 그런 다음 표시 플래그( )를 1로 설정하여found
동일한 디렉터리( )에 있는 다른 파일이 표시되지 않도록 합니다.$path
find
디렉터리 트리가 작지 않으면 코드는 본질적으로 호스트에 종속되며 상당한 운영 비용이 듭니다.