저는 쉘 스크립팅의 새로운 기술을 배우려고 노력하고 있습니다. 이제 선생님으로부터 파일을 새 디렉터리로 이동하는 방법에 대한 강의를 들었습니다.
질문
파일 패턴이 있습니다
A_20180423_0015 B_20180501_0045 C_20180426_0045
/new/destpath/A/20180423/0015,0030,0045와 같은 디렉터리로 파일을 이동하려는 경우 각 디렉터리에는 3개의 파일이 있습니다.
내 대본에는
#! /bin/bash
cd /app/Moving/DEST_PATH
mkdir A B C D
cd /app/Moving/DEST_PATH/A
MakesubA=$(for itype in A;do for ((i=1;i<=10;i++));do for ((itime=15;itime<=45;itime=itime+15));do mkdir ${itype}_$(date --date "${i} day ago" +"%Y%m%d")_00${itime} ;done;done;done)
cd ..
cd /app/Moving/DEST_PATH/B
MakesubB=$(for itype in B;do for ((i=1;i<=10;i++));do for ((itime=15;itime<=45;itime=itime+15));do mkdir ${itype}_$(date --date "${i} day ago" +"%Y%m%d")_00${itime} ;done;done;done)
cd ..
cd /app/Moving/DEST_PATH/C
MakesubC=$(for itype in C;do for ((i=1;i<=10;i++));do for ((itime=15;itime<=45;itime=itime+15));do mkdir ${itype}_$(date --date "${i} day ago" +"%Y%m%d")_00${itime} ;done;done;done)
cd ..
cd /app/Moving/DEST_PATH/D
MakesubD=$(for itype in D;do for ((i=1;i<=10;i++));do for ((itime=15;itime<=45;itime=itime+15));do mkdir ${itype}_$(date --date "${i} day ago" +"%Y%m%d")_00${itime} ;done;done;done)
cd ..
루프 등을 사용하여 알아내려고 노력했지만 각 디렉터리에 대한 각 파일을 선택하는 데 어떤 것을 사용해야 할지 모르겠습니다.
답변1
파일에는 기본적으로 파일 이름에 인코딩된 대상 경로가 있습니다.
호출되는 파일은 원본 파일 이름과 동일한 경로 이름이지만 밑줄이 슬래시로 대체된 ( 디렉토리에 있는 파일의 새 이름 으로 가정 ) A_20180423_0015
로 이동해야 합니다 .A/20180423/0015
0015
A/20180423
이는 이 연습이 문자열의 문자 교체에 관한 것임을 의미합니다.
대상이 이미 파일의 파일 이름에 인코딩되어 있으므로 가능한 모든 날짜에 대해 대상 디렉터리를 반복하고 생성할 필요가 없습니다.
원본 파일이 어디에 있는지, 또는 원본 파일을 [A-Z]_*_*
패턴으로 사용하여 현재 디렉터리에서 일치시킬 수 있는지 완전히 확신할 수 없습니다(할 수 있다고 가정합니다).
for source_filename in [A-Z]_*_*; do
target_pathname=${source_filename//_//}
mkdir -p "${target_pathname%/*}"
mv "$source_filename" "$target_pathname"
done
우리가 시작하면
.
|-- A_20180423_0015
|-- B_20180501_0045
`-- C_20180426_0045
0 directory, 3 files
...위의 코드를 실행하면 다음과 같은 결과를 얻을 수 있습니다.
.
|-- A/
| `-- 20180423/
| `-- 0015
|-- B/
| `-- 20180501/
| `-- 0045
`-- C/
`-- 20180426/
`-- 0045
6 directories, 3 files
댓글 코드:
# Loop over all names in the current directory that matches the given pattern.
for source_filename in [A-Z]_*_*; do
# Replace all underscores in the found name with slashes.
# We use bash's ${parameter//pattern/replacement} pattern substitution
# to do this.
# If you need to append a path to this, just do so with
# target_pathname="/some/path/${source_filename//_//}"
target_pathname=${source_filename//_//}
# Make sure that the target directory exists.
# With ${target_pathname%/*} we remove the filename component of
# the target pathname to get the directory of the destination file.
# You may change this to the following if you wish:
# mkdir -p "$( dirname "$target_pathname" )"
mkdir -p "${target_pathname%/*}"
# Move the file into place.
mv "$source_filename" "$target_pathname"
done
질문을 잘못 이해하여 파일이 원래 파일 이름을 유지해야 하지만 파일 이름에 해당하는 디렉터리로 이동해야 하는 경우(예: A_20180423_0015
로 이동해야 하는 경우 A/20180423/0015/A_20180423_0015
) 위 코드에서 몇 문자만 변경하면 됩니다.
mkdir -p "${target_pathname%/*}"
로 변경
mkdir -p "$target_pathname"
이 변화는 우리를 가져올 것입니다
.
|-- A/
| `-- 20180423/
| `-- 0015/
| `-- A_20180423_0015
|-- B/
| `-- 20180501/
| `-- 0045/
| `-- B_20180501_0045
`-- C/
`-- 20180426/
`-- 0045/
`-- C_20180426_0045
9 directories, 3 files
소스 파일이 현재 디렉터리가 아닌 다른 디렉터리에 있는 경우:
for source_pathname in /some/source/path/[A-Z]_*_*; do
source_filename=${source_pathname##*/}
target_pathname="some/target/path/${source_filename//_//}"
mkdir -p "$target_pathname"
mv "$source_pathname" "$target_pathname"
done