파일을 생성하고 파일 이름의 날짜 및 시간을 기준으로 폴더에 정렬합니다.

파일을 생성하고 파일 이름의 날짜 및 시간을 기준으로 폴더에 정렬합니다.

Main내 폴더에는 다음과 같은 이름의 파일이 많이 있습니다 .

2021_10_15_23_35_SIP_CDR_pid3894_ins2_thread_1_4718.csv.gz
2021_11_24_21_15_Gi_pid25961_ins2_thread_1_6438.csv.gz  2021_11_25_20_55_Gi_pid29741_ins5_thread_4_7540.csv.gz
2021_11_24_21_15_Gi_pid27095_ins2_thread_1_6485.csv.gz  2021_11_25_20_55_Gi_pid30842_ins3_thread_2_7489.csv.gz
2021_11_24_21_15_Gi_pid27095_ins3_thread_2_6485.csv.gz  2021_11_25_20_55_Gi_pid30842_ins4_thread_3_7488.csv.gz
2021_11_24_21_15_Gi_pid27095_ins4_thread_3_6485.csv.gz  2021_11_25_20_55_Gi_pid30842_ins5_thread_4_7489.csv.gz
2021_11_24_21_15_Gi_pid681_ins5_thread_4_6457.csv.gz

처음 10자는 날짜를 나타내고 그 뒤에 숫자(24시간 형식의 시간)가 표시됩니다. 나머지는 무시할 수 있는 파일 세부 정보입니다.

Main파일 이름의 날짜를 기준으로 해당 폴더 안에 폴더를 만든 다음 파일 이름의 시간을 기준으로 날짜 폴더 안에 다른 폴더를 만들고 싶습니다 . 궁극적으로 Main폴더의 파일을 해당 시간 폴더로 이동 하고 싶습니다 .

Main -> Date -> hh -> file.csv.gz

예를 들어, 폴더 2021_11_24_21_15_Gi_pid27095_ins3_thread_2_6485.csv.gz의 파일은 Main다음 경로를 가진 이와 같은 폴더에 저장됩니다.Main/2021_11_24/21/2021_11_24_21_15_Gi_pid27095_ins3_thread_2_6485.csv.gz

위에서 언급한 대로 폴더의 파일 그룹화를 위해 bash 스크립트를 사용하는 데 도움을 주실 수 있나요?

답변1

perl rename유틸리티를 사용하십시오:

file-rename참고: Perl 이름 바꾸기는 , perl-rename, 또는 이라고도 합니다 prename. 기능과 명령줄 옵션이 완전히 다르고 호환되지 않는 rename유틸리티와 혼동 하지 마십시오. util-linuxperl rename은 Debian...IIRC의 기본 이름 바꾸기이며 prenameCentos의 패키지에 있으며 명령 prenamerename.

$ rename -n 'if (m/(^\d{4}_\d\d_\d\d)_(\d\d)/) {
               my ($date,$hour) = ($1,$2);
               my $dir = "./$date/$hour/";
               mkdir $date;
               mkdir $dir;
               s=^=$dir=
             }' *
rename(2021_10_15_23_35_SIP_CDR_pid3894_ins2_thread_1_4718.csv.gz, ./2021_10_15/23/2021_10_15_23_35_SIP_CDR_pid3894_ins2_thread_1_4718.csv.gz)
rename(2021_11_24_21_15_Gi_pid25961_ins2_thread_1_6438.csv.gz, ./2021_11_24/21/2021_11_24_21_15_Gi_pid25961_ins2_thread_1_6438.csv.gz)
rename(2021_11_24_21_15_Gi_pid27095_ins2_thread_1_6485.csv.gz, ./2021_11_24/21/2021_11_24_21_15_Gi_pid27095_ins2_thread_1_6485.csv.gz)
rename(2021_11_24_21_15_Gi_pid27095_ins3_thread_2_6485.csv.gz, ./2021_11_24/21/2021_11_24_21_15_Gi_pid27095_ins3_thread_2_6485.csv.gz)
rename(2021_11_24_21_15_Gi_pid27095_ins4_thread_3_6485.csv.gz, ./2021_11_24/21/2021_11_24_21_15_Gi_pid27095_ins4_thread_3_6485.csv.gz)
rename(2021_11_24_21_15_Gi_pid681_ins5_thread_4_6457.csv.gz, ./2021_11_24/21/2021_11_24_21_15_Gi_pid681_ins5_thread_4_6457.csv.gz)
rename(2021_11_25_20_55_Gi_pid29741_ins5_thread_4_7540.csv.gz, ./2021_11_25/20/2021_11_25_20_55_Gi_pid29741_ins5_thread_4_7540.csv.gz)
rename(2021_11_25_20_55_Gi_pid30842_ins3_thread_2_7489.csv.gz, ./2021_11_25/20/2021_11_25_20_55_Gi_pid30842_ins3_thread_2_7489.csv.gz)
rename(2021_11_25_20_55_Gi_pid30842_ins4_thread_3_7488.csv.gz, ./2021_11_25/20/2021_11_25_20_55_Gi_pid30842_ins4_thread_3_7488.csv.gz)
rename(2021_11_25_20_55_Gi_pid30842_ins5_thread_4_7489.csv.gz, ./2021_11_25/20/2021_11_25_20_55_Gi_pid30842_ins5_thread_4_7489.csv.gz)

이것은 -n시험 실행 옵션으로 실제로 수행하는 것이 아니라 수행할 작업만 표시합니다. -v이름 바꾸기 스크립트가 원하는 작업을 수행할 것이라고 확신하면 해당 스크립트를 제거하십시오(또는 자세한 출력으로 바꾸십시오).

스크립트는 먼저 추출하여 작동합니다.날짜그리고시간각 파일 이름의 일부(일치하지 않는 파일 이름 건너뛰기) 그런 다음 date디렉터리를 생성한 date/hour다음 파일 이름을 해당 디렉터리로 바꿉니다.

이는 파일 이름이 현재 디렉터리에 있다고 가정합니다. 그렇지 않은 경우 m//첫 번째 줄에서 일치하는 정규식을 조정해야 합니다.그리고s===두 번째 줄의 대체 정규식입니다.


사용된 대체 버전파일 경로perl 코어 모듈(perl에 포함됨)을 두 번 사용하는 대신 mkdir( 함수는 쉘 명령 make_path처럼 작동함 ):mkdir -p

$ rename -v 'BEGIN {use File::Path qw(make_path)};
             if (m/(^\d{4}_\d\d_\d\d)_(\d\d)/) {
               my $dir = "./$1/$2/";
               make_path $dir;
               s=^=$dir=
             }' *
2021_10_15_23_35_SIP_CDR_pid3894_ins2_thread_1_4718.csv.gz renamed as ./2021_10_15/23/2021_10_15_23_35_SIP_CDR_pid3894_ins2_thread_1_4718.csv.gz
2021_11_24_21_15_Gi_pid25961_ins2_thread_1_6438.csv.gz renamed as ./2021_11_24/21/2021_11_24_21_15_Gi_pid25961_ins2_thread_1_6438.csv.gz
2021_11_24_21_15_Gi_pid27095_ins2_thread_1_6485.csv.gz renamed as ./2021_11_24/21/2021_11_24_21_15_Gi_pid27095_ins2_thread_1_6485.csv.gz
2021_11_24_21_15_Gi_pid27095_ins3_thread_2_6485.csv.gz renamed as ./2021_11_24/21/2021_11_24_21_15_Gi_pid27095_ins3_thread_2_6485.csv.gz
2021_11_24_21_15_Gi_pid27095_ins4_thread_3_6485.csv.gz renamed as ./2021_11_24/21/2021_11_24_21_15_Gi_pid27095_ins4_thread_3_6485.csv.gz
2021_11_24_21_15_Gi_pid681_ins5_thread_4_6457.csv.gz renamed as ./2021_11_24/21/2021_11_24_21_15_Gi_pid681_ins5_thread_4_6457.csv.gz
2021_11_25_20_55_Gi_pid29741_ins5_thread_4_7540.csv.gz renamed as ./2021_11_25/20/2021_11_25_20_55_Gi_pid29741_ins5_thread_4_7540.csv.gz
2021_11_25_20_55_Gi_pid30842_ins3_thread_2_7489.csv.gz renamed as ./2021_11_25/20/2021_11_25_20_55_Gi_pid30842_ins3_thread_2_7489.csv.gz
2021_11_25_20_55_Gi_pid30842_ins4_thread_3_7488.csv.gz renamed as ./2021_11_25/20/2021_11_25_20_55_Gi_pid30842_ins4_thread_3_7488.csv.gz
2021_11_25_20_55_Gi_pid30842_ins5_thread_4_7489.csv.gz renamed as ./2021_11_25/20/2021_11_25_20_55_Gi_pid30842_ins5_thread_4_7489.csv.gz

이것은 첫 번째 버전보다 실제로 낫지는 않지만 Perl 코드, Perl 모듈을 사용하여 파일 이름을 바꾸거나 파일을 이동할 수 있음을 보여줍니다.


세 번째 버전은 다음을 사용합니다.파일::기본 이름입력 경로 이름을 $path$file부분으로 분할합니다. 현재 디렉터리나 다른 디렉터리의 파일 이름을 처리할 수 있습니다. File::Basename핵심 Perl 모듈이므로 Perl에 포함되어 있습니다. 이는 세 가지 유용한 기능을 제공하며 basename()( dirname()동일한 이름의 셸 도구와 유사하게 작동) fileparse()이는 기본 이름과 디렉터리를 별도의 변수로 추출하기 위해 이 스크립트에서 사용한 것입니다.

rename -n 'BEGIN {use File::Path qw(make_path); use File::Basename};
           my ($file, $path) = fileparse($_);
           if ($file =~ m/(\d{4}_\d\d_\d\d)_(\d\d)/) {
             my $dir = "$path/$1/$2";
             make_path $dir;
             $_ = "$dir/$file"
           }' /home/cas/rename-test/*
rename(/home/cas/rename-test/2021_10_15_23_35_SIP_CDR_pid3894_ins2_thread_1_4718.csv.gz, /home/cas/rename-test/2021_10_15/23/2021_10_15_23_35_SIP_CDR_pid3894_ins2_thread_1_4718.csv.gz)
rename(/home/cas/rename-test/2021_11_24_21_15_Gi_pid25961_ins2_thread_1_6438.csv.gz, /home/cas/rename-test/2021_11_24/21/2021_11_24_21_15_Gi_pid25961_ins2_thread_1_6438.csv.gz)
rename(/home/cas/rename-test/2021_11_24_21_15_Gi_pid27095_ins2_thread_1_6485.csv.gz, /home/cas/rename-test/2021_11_24/21/2021_11_24_21_15_Gi_pid27095_ins2_thread_1_6485.csv.gz)
rename(/home/cas/rename-test/2021_11_24_21_15_Gi_pid27095_ins3_thread_2_6485.csv.gz, /home/cas/rename-test/2021_11_24/21/2021_11_24_21_15_Gi_pid27095_ins3_thread_2_6485.csv.gz)
rename(/home/cas/rename-test/2021_11_24_21_15_Gi_pid27095_ins4_thread_3_6485.csv.gz, /home/cas/rename-test/2021_11_24/21/2021_11_24_21_15_Gi_pid27095_ins4_thread_3_6485.csv.gz)
rename(/home/cas/rename-test/2021_11_24_21_15_Gi_pid681_ins5_thread_4_6457.csv.gz, /home/cas/rename-test/2021_11_24/21/2021_11_24_21_15_Gi_pid681_ins5_thread_4_6457.csv.gz)
rename(/home/cas/rename-test/2021_11_25_20_55_Gi_pid29741_ins5_thread_4_7540.csv.gz, /home/cas/rename-test/2021_11_25/20/2021_11_25_20_55_Gi_pid29741_ins5_thread_4_7540.csv.gz)
rename(/home/cas/rename-test/2021_11_25_20_55_Gi_pid30842_ins3_thread_2_7489.csv.gz, /home/cas/rename-test/2021_11_25/20/2021_11_25_20_55_Gi_pid30842_ins3_thread_2_7489.csv.gz)
rename(/home/cas/rename-test/2021_11_25_20_55_Gi_pid30842_ins4_thread_3_7488.csv.gz, /home/cas/rename-test/2021_11_25/20/2021_11_25_20_55_Gi_pid30842_ins4_thread_3_7488.csv.gz)
rename(/home/cas/rename-test/2021_11_25_20_55_Gi_pid30842_ins5_thread_4_7489.csv.gz, /home/cas/rename-test/2021_11_25/20/2021_11_25_20_55_Gi_pid30842_ins5_thread_4_7489.csv.gz)

그런데, 파일을 완전히 다른 경로로 이동하도록 수정하는 것은 쉽지 않습니다. 다음 my $dir = "/my/new/path/$1/$2";과 같이 하십시오.my $dir = "$path/$1/$2";

핵심은 방법을 이해하는 것입니다.진주 rename유틸리티는 다음과 같이 작동합니다.만약에 그리고 만약에이름 바꾸기 스크립트는 $_변수를 수정한 후 파일 이름을 새 값으로 바꾸려고 시도합니다 $_. 변경되지 않은 경우 $_이름 바꾸기가 시도되지 않습니다. 그렇기 때문에 다음을 사용할 수 있습니다.어느파일 이름을 바꾸는 Perl 코드 - 당신이 해야 할 일은 $_대부분 매우 간단한 sed이름 바꾸기 스크립트(예: rename 's/ +/_/g' *파일 이름의 공백 이름을 밑줄로 바꾸기)를 사용하지만 이름 바꾸기 알고리즘은 필요에 따라 사용자 정의할 수 있습니다. 그리고 복잡성.

$_Perl에서 매우 중요한 변수입니다. 파일 핸들 및 루프 반복기의 입력을 보관하는 기본 변수로 사용됩니다.프로그래머가 지정하지 않은 경우. m//, s///, 등 여러 연산자 tr///의 기본 피연산자 로 사용되기도 합니다.많은(전부는 아님) 기능. 보기 man perlvar및 검색 $_(less as 에서 이스케이프해야 함 \$_)


그런데 이전에 언급하지 않은 한 가지는 rename명령줄이나 표준 입력에서 파일 이름을 인수로 사용할 수 있다는 것입니다. 기본값은 표준 입력에서 개행으로 구분된 입력입니다(따라서 개행이 포함된 파일 이름에서는 작동하지 않습니다. 짜증나지만 완벽하게 유효한 가능성입니다). -0인수를 사용하여 개행 구분 대신 NUL 구분 입력을 사용하도록 할 수 있습니다 . 따라서 NUL로 구분된 파일 이름 목록을 생성할 수 있는 모든 입력에서 입력을 가져오는 모든 파일 이름을 사용할 수 있습니다(예 find ... -print0: , 하지만 더 좋을 수도 있습니다. find옵션 만 사용하려면 -exec ... {} +).

rename-f또는 옵션 을 사용하지 않으면 기존 파일의 파일 이름 바꾸기도 거부됩니다 --force.

답변2

대신 디렉토리에서 사용하려면 다음을 수행 zsh하십시오.bashMain

zmodload zsh/files # to get builtin mkdir/mv to speed things up

mkdmv() { mkdir -p -- $2:h && mv -- "$@"; }
zmv -n -P mkdmv '(<->_<->_<->)_(<->)_*.csv' '$1/$2/$f'

-n(만족하면 시험 실행을 삭제합니다).

zmv충돌 발생 시 데이터 손실을 방지하기 위해 작업을 수행하기 전에 온전성 검사가 실행됩니다. 이는 대부분의 다른 대량 이름 바꾸기 유틸리티에 비해 장점 중 하나입니다.

<->모든 ASCII 숫자 시퀀스와 일치합니다. 보다 구체적인 일치를 원하는 경우 (<1970-2099>_<1-12>_<1-31>)_(<0-23>)_*.csv그렇게 할 수 있습니다.

관련 정보