예를 들어 이라는 홈 디렉터리가 있습니다 main
. 이 홈 디렉터리에는 몇 개의 폴더가 있고 그 안에는 ccc
ddd
및 이라는 이름의 세 개의 폴더가 있는데 lll
, 이 폴더들만 찾아서 처리하고 싶습니다. 각 하위 폴더에는 세 개의 하위 폴더 모두에 동일한 이름을 가진 폴더가 있으므로 ccc
ddd
lll
하위 폴더에는 동일한 이름의 폴더가 포함됩니다.
그런 다음 그 안의 각 하위 폴더에는 this 등과 ccc
ddd
lll
같은 특정 이름을 가진 여러 개의 파일이 있습니다 .c_000
d_000
l_000
c_001
d_001
l_001
내가 한 첫 번째 일은 아래와 같이 파일 이름의 시작 부분에 두 개의 상위 디렉터리가 추가되도록 파일 이름을 바꾸는 것이었습니다 ccc_foo1_c_000
ddd_foo1_d_000
lll_foo1_l_000
. 스크립트에서 이 작업을 수행하는 방법을 제안할 수 있는 사람이 있는지 물었습니다 .sh
.
내 홈 폴더의 간단한 트리 구조는 다음과 같습니다.
.
`-- main
|-- ccc
| `-- foO1
| | |-- c_000
| | `-- c_001
| |
-- foo2
| |-- c_000
| `-- c_001
|
|
|-- ddd
| `-- foO1
| | |-- d_000
| | `-- d_001
| |
-- foo2
| |-- d_000
| `-- d_001
|-- lll
| `-- foO1
| | |-- l_000
| | `-- l_001
| |
| -- foo2
| |-- l_000
| `-- l_001
|
|-- aaa
|-- bbb
답변1
다음을 수행할 수 있습니다.
for dir in ccc ddd lll; do
find "main/$dir" -type f -print0 |
while IFS= read -r -d '' f; do
dd=$(dirname "$f")
new="${f/main\/}"
new="${new//\//_}"
mv "$f" "$dd"/"$new"
done
done
위 스크립트를 완료하면 파일은 다음과 같습니다.
.
`-- main
|-- ccc
| |-- fo01
| | |-- ccc_fo01_c_000
| | `-- ccc_fo01_c_001
| `-- fo02
| |-- ccc_fo02_c_000
| `-- ccc_fo02_c_001
|-- ddd
| |-- fo01
| | |-- ddd_fo01_d_000
| | `-- ddd_fo01_d_001
| `-- fo02
| |-- ddd_fo02_d_000
| `-- ddd_fo02_d_001
`-- lll
|-- fo01
| |-- lll_fo01_l_000
| `-- lll_fo01_l_001
`-- fo02
|-- lll_fo02_l_000
`-- lll_fo02_l_001
설명하다
for dir in ccc ddd lll; do ...; done
: 이 세 개의 디렉토리 이름에 대해서만 이 작업을 수행하고 개별적으로$dir
.find "main/$dir" -type f -print0 |
type f
: ( ) 안의 모든 파일을 찾아 빈 문자열( )로 구분하여 인쇄하여 파일/디렉터리 이름에 개행 문자가 포함되어 있어도 제대로 작동하는지 확인합니다main/$dir
.-print0
while IFS= read -r -d '' f; do
: 이는 결과를 반복하여find
각 결과를 로 저장합니다$f
. 백슬래시가 특별히 처리되지 않고 null로 구분된 입력을 읽을 수 있도록IFS=
공백을 깨는 것을 피해야 합니다 .-r
-d ''
dd=$(dirname "$f")
:$dd
Now는 현재 파일이 위치한 디렉터리입니다. 예를 들어,main/ccc/fo01
.new="${f/main\/}"
: 쉘을 사용하고 있습니다.문자열 연산main/
파일 경로에서 문자열을 제거하는 기능.new="${new//\//_}"
:위에서 언급했듯이 이제 모든 것을 밑줄로 바꿉니다/
. 그러면 비슷한 문자열이 생성됩니다ccc_fo01_c000
.mv "$f" "$dd"/"$new"
: 마지막으로 원본 파일 의$f
이름 을$dd/$new
.$dd
$new
실제로 이 작업을 수행하기 전에 테스트하기 echo
전에 추가하는 것이 좋습니다 mv
.
답변2
이것은 파일을 반복하고 이름의 디렉터리 부분을 구문 분석하여 하나씩 이름을 바꾸는 간단한 POSIX 셸 솔루션입니다.
for x in ccc/*/* ddd/*/* lll/*/*; do
dir2=${x%/*}; dir1=${dir2%/*}; dir2=${dir2#"$dir1"}
mv -- "$x" "${x%/*}/${dir1}_${dir2}_${x##*/}"
done
Bash에서는 다음을 사용할 수 있습니다.매개변수 확장파일 이름 구문 분석을 방지하기 위한 문자열 대체 기능입니다.
for x in ccc/*/* ddd/*/* lll/*/*; do
mv -- "$x" "${x%/*}/${x//\//_}"
done
zsh에서는 사용할 수 있습니다zmv
패턴에 따라 파일 이름을 바꿉니다.
autoload -U zmv
zmv '(ccc|ddd|lll)/(*)/(*)' '$1/$2/${1}_${2}_$3'
답변3
소프트 코딩된 솔루션의 경우 디렉터리에서 실행됩니다 main
.
#!/bin/bash
for f in $(find . -name '*_00*'); do
mv "$f" "$(dirname "$f")/$(dirname "${f:2}" | tr "/" "_")_$(basename $f)"
done
이는 모든 디렉토리를 재귀적으로 탐색하여 패턴이 포함된 모든 파일을 찾아야 합니다 *_00*
. 각 파일은 경로( $(dirname $"f")
), 밑줄과 제거된 처음 두 문자를 포함하는 변환된 경로( $(dirname "${f:2}" | tr "/" "_")
), 원본 파일 이름 자체( )의 $(basename $f)
조합을 사용하여 개별적으로 이름이 변경됩니다 .