지난 몇 년 동안 마지막으로 수정된 파일이 포함된 큰 디렉터리가 있습니다. 하위 디렉터리를 생성하는 대화형 bash 셸에 한 번 입력할 수 있는 간단한 명령이 있습니까? 각각 4자리 연도로 이름이 지정되고 그 안에 있는 정보를 신뢰할 수 없을 때 해당 파일을 다음 위치로 이동하십시오. 파일의 나이와 관련된 파일 이름이 있는 각 하위 디렉터리를 확인하고 마지막으로 내가 실행하는 모든 것이 제대로 작동하고 파일이나 데이터가 손실되지 않았는지 확인하시겠습니까?
예를 들어, 다음과 같은 완전히 잘못된 예가 있습니다.
$ cd ~/Documents
$ ls -lhrt
...
-rw-r--r-- 4 user user 4.0K Jun 29 2017 oldfile.txt
-rw-r--r-- 4 user user 4.0K May 15 2018 2018file.md
-rw-r--r-- 4 user user 4.0K Apr 14 2019 04.dat
-rw-r--r-- 4 user user 4.0K Jul 21 2019 somepage.html
drw-r--r-- 4 user user 4.0K Jul 21 2019 somepage_files
-rw-r--r-- 4 user user 4.0K Mar 13 2020 march.dat
-rw-r--r-- 4 user user 4.0K Feb 12 18:03 file02.dat
-rw-r--r-- 4 user user 4.0K Oct 11 18:03 OctReport.txt
완료되면 다음 결과를 얻고 싶습니다.
$ cd ~/Documents
$ find .
.
./2017
./2017/oldfile.txt
./2018
./2018/2018file.md
./2019
./2019/04.dat
./2019/somepage.html
./2019/somepage_files
./2019/somepage_files/...
./2020
./2020/march.dat
./2021
./2021/file02.dat
./2021/OctReport.txt
답변1
for
루프를 사용하여 디렉토리를 생성하여 date
각 파일의 수정 연도를 얻을 수 있습니다(여기서는 GNU date
또는 해당 옵션이 호환된다고 가정). -r
그러면 각 파일이 해당 디렉터리로 이동됩니다.
for file in *; do
[ ! -L "$file" ] &&
dir_name=$(date -r "$file" +%Y) &&
mkdir -p "$dir_name" &&
mv -- "$file" "$dir_name"
done
답변2
사용진주 rename
rename
유틸리티(util-linux 또는 다른 유틸리티와 혼동하지 마십시오 rename
):
$ rename -n -e 'BEGIN {use POSIX};
next unless -f $_;
my $Y = strftime "%Y", localtime((stat $_)[9]);
mkdir $Y unless -d $Y;
s=^=$Y/=' *
rename(04.dat, 2019/04.dat)
rename(2018file.md, 2018/2018file.md)
rename(file02.dat, 2021/file02.dat)
rename(march.dat, 2020/march.dat)
rename(OctReport.txt, 2021/OctReport.txt)
rename(oldfile.txt, 2017/oldfile.txt)
rename(somepage_files, 2019/somepage_files)
rename(somepage.html, 2019/somepage.html)
이 -n
옵션을 사용하면 시험 실행이 됩니다. -v
원하는 대로 작동한다고 확신하면 제거하세요(또는 자세한 출력으로 바꾸세요). 예를 들어
$ find . -type f -ls
864326 9 drwxr-xr-x 2 cas cas 10 Dec 22 18:08 .
863863 1 -rw-r--r-- 1 cas cas 0 Oct 11 18:03 ./OctReport.txt
863999 1 -rw-r--r-- 1 cas cas 0 Jul 21 2019 ./somepage_files
864123 1 -rw-r--r-- 1 cas cas 0 Mar 13 2020 ./march.dat
863997 1 -rw-r--r-- 1 cas cas 0 May 15 2018 ./2018file.md
864122 1 -rw-r--r-- 1 cas cas 0 Apr 14 2019 ./04.dat
863862 1 -rw-r--r-- 1 cas cas 0 Feb 12 2021 ./file02.dat
863998 1 -rw-r--r-- 1 cas cas 0 Jul 21 2019 ./somepage.html
863996 1 -rw-r--r-- 1 cas cas 0 Jun 29 2017 ./oldfile.txt
$ rename -v -e 'BEGIN {use POSIX}; next unless -f $_; my $Y = strftime "%Y", localtime((stat $_)[9]); mkdir $Y unless -d $Y; s=^=$Y/=' *
04.dat renamed as 2019/04.dat
2018file.md renamed as 2018/2018file.md
file02.dat renamed as 2021/file02.dat
march.dat renamed as 2020/march.dat
OctReport.txt renamed as 2021/OctReport.txt
oldfile.txt renamed as 2017/oldfile.txt
somepage_files renamed as 2019/somepage_files
somepage.html renamed as 2019/somepage.html
$ find . -type f -ls
863996 1 -rw-r--r-- 1 cas cas 0 Jun 29 2017 ./2017/oldfile.txt
863862 1 -rw-r--r-- 1 cas cas 0 Feb 12 2021 ./2021/file02.dat
863863 1 -rw-r--r-- 1 cas cas 0 Oct 11 18:03 ./2021/OctReport.txt
863999 1 -rw-r--r-- 1 cas cas 0 Jul 21 2019 ./2019/somepage_files
864122 1 -rw-r--r-- 1 cas cas 0 Apr 14 2019 ./2019/04.dat
863998 1 -rw-r--r-- 1 cas cas 0 Jul 21 2019 ./2019/somepage.html
864123 1 -rw-r--r-- 1 cas cas 0 Mar 13 2020 ./2020/march.dat
863997 1 -rw-r--r-- 1 cas cas 0 May 15 2018 ./2018/2018file.md
이러한 Perl 함수에 대한 자세한 내용은 perldoc -f stat
및를 참조하세요. perldoc -f localtime
자세한 내용은 strftime()
에서 확인할 수 있습니다 perldoc POSIX
.
그런데 rename
명령줄이나 표준 입력에서 파일 이름을 인수로 전달할 수 있습니다(이름 바꾸기 옵션을 사용하는 경우 NUL로 구분된 파일 이름을 사용할 수도 있습니다. -0
이는 개행 및 기타 성가신 문자가 포함된 파일 이름을 처리할 때 유용합니다). . 바라보다 man rename
.
답변3
find
여기에서 유용할 수 있습니다. printf
GNU-가 필요합니다 find
.
필요한 디렉토리 생성
find -maxdepth 1 -mindepth 1 -type f -printf '%TY\n' | sort -u | xargs mkdir
그에 따라 파일을 이동하십시오.
find -maxdepth 1 -mindepth 1 -type f -printf '%f\0%TY/%f\0' | xargs -0 -l2 mv --
2단계에서 NUL로 구분된 이름을 사용하면 이 방법이 공백, 개행 등을 포함하는 파일 이름에 매우 강력해집니다.
디렉터리를 포함하는 경우(텍스트에는 파일이라고 표시되어 있지만 예제에는 디렉터리가 포함되어 있음) 2단계에서 연도 이름이 지정된 디렉터리를 제외해야 합니다.
find -maxdepth 1 -mindepth 1 ! -name '[12][0129][0-9][0-9]' -printf '%f\0%TY/%f\0' | xargs -0 -l2 mv
...1000보다 오래되었거나 2999보다 이후의 파일이 없다고 가정합니다.
카탈로그의 연령도 업데이트하고 싶으신가요? 그런 다음 다음을 실행하십시오.
for dir in [12][0129][0-9][0-9] ; do
touch -d ${dir}-01-01 $dir
done
이렇게 하면 디렉터리의 나이가 해당 연도의 1월 1일로 설정되고 향후 날짜 기반 검색이 단순화됩니다.