이것은 이 포럼의 새로운 내용이지만 RHEL이나 스크립팅에 익숙하지 않습니다. 그런데 이게 좀 마음에 걸리네요. 다음 파일이 있습니다.
2019-05-01-00.34.00.msg
2019-05-02-00.36.00.msg
2019-06-14-01.38.00.msg
다음과 같은 디렉토리에 저장하고 싶습니다.
/2019/05/01/<Filename>
/2019/05/02/<Filename>
/2019/06/14/<Filename>
또한 디렉토리에 넣을 때 현재 파일 이름을 유지하고 싶습니다. 또한 bash를 사용하여 이 작업을 수행하고 싶습니다.
어떤 아이디어가 있나요?
답변1
이름을 반복하고 이름을 분할한 -
다음 mkdir -p
존재하지 않는 경우 디렉터리를 만들고 마지막으로 이동할 수 있습니다. 이 같은:
for file in *msg; do
IFS="-" read -r year month day rest <<< "$file"
dir="$year/$month/$day/"
mkdir -p -- "$dir"
mv -- "$file" "$dir"
done
답변2
이는 Perl 이름 바꾸기 도구(아니요util-linux 패키지의 이름 바꾸기 도구). 예를 들어
설정:
$ touch 2019-05-01-00.34.00.msg 2019-05-02-00.36.00.msg 2019-06-14-01.38.00.msg
$ ls -l
total 2
-rw-r--r-- 1 cas cas 0 Oct 16 20:56 2019-05-01-00.34.00.msg
-rw-r--r-- 1 cas cas 0 Oct 16 20:56 2019-05-02-00.36.00.msg
-rw-r--r-- 1 cas cas 0 Oct 16 20:56 2019-06-14-01.38.00.msg
이름을 바꿔라:
rename -n '
use File::Path qw(make_path);
if (-f $_ && m/^\d{4}-\d{2}-\d{2}-/) {
my ($y,$m,$d,$f) = split /-/,$_,4;
make_path("$y/$m/$d");
$_ = "$y/$m/$d/$f";
}' *.msg
스크립트는 먼저 비정규 파일( -f
) 또는 패턴과 일치하지 않는 파일 이름을 무시합니다 ^YYYY-MM-DD-
. 이렇게 하면 정크 입력이 제공되면 원치 않는 디렉터리가 생성되는 것을 방지할 수 있습니다.
파일 이름을 네 가지 요소로 나눕니다. 처음 3개는 파일 이름에 포함된 연월일( $y
, $m
및 $d
)이고, 네 번째는 파일 이름의 나머지 부분( $f
)입니다.
make_path()
다음의 기능을 사용합니다 .파일 경로YYYY/
YYYY/MM/
, 및 에 대한 디렉터리를 반복적으로 생성하기 위한 표준 모듈입니다 ( 명령 의 옵션 YYYY/MM/DD/
과 유사 ). Perl 기능을 세 번 실행할 수도 있었지만 .-p
mkdir
mkdir()
File::Path
$_
그런 다음 같음을 설정하여 파일 이름을 올바른 디렉터리로 변경(즉, 이동)합니다."$y/$m/$d/$f"
이것이 Perl이 작동하는 방식의 핵심입니다 rename
. 당신은 그것을 사용할 수 있습니다어느s/foo/bar/
간단한 검색 및 교체 스타일부터 이 답변에 있는 것보다 훨씬 더 복잡한 스크립트에 이르기까지 Perl 코드 . 코드가 변경되면 $_
파일 이름이 변경됩니다. 변경되지 않으면 $_
이름이 바뀌지 않습니다.
참고: 이 줄은 rename
' -n
옵션을 사용하므로시운전오직. 실제로 파일 이름을 바꾸려면 파일을 제거 하거나 다음과 같이 자세한 출력으로 -n
변경하세요 .-v
2019-05-01-00.34.00.msg renamed as 2019/05/01/00.34.00.msg
2019-05-02-00.36.00.msg renamed as 2019/05/02/00.36.00.msg
2019-06-14-01.38.00.msg renamed as 2019/06/14/01.38.00.msg
그런데, 파일 이름은 위에 표시된 것처럼 명령줄에 제공되거나 스크립트에 파이프될 수 있습니다( 예를 들어 NUL로 구분된 목록을 출력할 수 있는 다른 입력 파일 이름을 허용할 수 있는 옵션이 rename
있습니다 ).-0
find ... -print0
마지막으로 rename
추가하세요 .아니요-f
aka 옵션을 사용하도록 지시하지 않는 한 기존 파일을 덮어씁니다 --force
.