
디렉터리를 다음 형식으로 어떻게 평면화할 수 있나요?
앞으로:./aaa/bbb/ccc.png
뒤쪽에:./aaa-bbb-ccc.png
답변1
여기에는 이미 좋은 답변이 있지만 다음에서 더 직관적이라고 생각합니다 bash
.
find aaa -type f -exec sh -c 'new=$(echo "{}" | tr "/" "-" | tr " " "_"); mv "{}" "$new"' \;
aaa
기존 디렉토리는 어디에 있습니까? 여기에 포함된 파일은 현재 디렉터리로 이동됩니다(aaa에는 빈 디렉터리만 남음). 이 두 호출은 tr
디렉터리와 공백을 처리합니다(슬래시를 이스케이프 처리하는 논리 없음 - 독자를 위한 연습).
나는 이것이 더 직관적이고 상대적으로 조정하기 쉽다고 생각합니다. find
즉, .png 파일만 찾으려면 매개변수를 변경할 수 있습니다. tr
통화를 변경하거나 필요한 경우 더 추가할 수 있습니다 . 제대로 작동하는지 시각적으로 확인하려면 echo
먼저 추가하고 추가 단계 없이 문제가 제대로 보이는 경우에만 반복하면 됩니다.mv
echo
find aaa -name \*.png -exec sh -c 'new=$(echo "{}" | tr "/" "-" | tr " " "_"); echo mv "{}" "$new"' \;
또한 ... 또는 ... find aaa
대신에 ... 를 사용했다는 점에 유의하십시오. 후자의 두 개는 최종 파일 이름에 흥미로운 흔적을 남길 것이기 때문입니다.find .
find aaa/
답변2
경고: 대부분의 명령을 브라우저에 직접 입력했습니다. 강사에게 경고하십시오.
zsh를 사용하고즈마브:
zmv -o -i -Qn '(**/)(*)(D)' '${1//\//-}$2'
설명: 이 패턴은 **/*
현재 디렉터리의 하위 디렉터리에 있는 모든 파일을 반복적으로 일치합니다(현재 디렉터리의 파일과 일치하지 않지만 이러한 파일의 이름을 바꿀 필요는 없습니다). 대괄호의 처음 두 쌍은 대체 텍스트에서 합계로 참조될 수 있는 $1
그룹 입니다. $2
마지막 대괄호 쌍을 추가하십시오.D
글로벌 예선이렇게 하면 파일이 누락되지 않습니다. 기존 파일을 덮어쓸지 여부를 묻는 메시지를 표시하기 위해 -o -i
이 -i
옵션을 전달하는 것을 의미합니다.mv
POSIX 도구만 사용하십시오.
find . -depth -exec sh -c '
for source; do
case $source in ./*/*)
target="$(printf %sz "${source#./}" | tr / -)";
mv -i -- "$source" "${target%z}";;
esac
done
' _ {} +
설명: 이 case
명령문은 현재 디렉토리와 현재 디렉토리의 최상위 레벨 하위 디렉토리를 생략합니다. 선행이 제거되고 모든 슬래시가 대시로 대체된 target
소스 파일 이름( )이 포함됩니다 . 마지막은 파일 이름이 개행으로 끝나는 것을 방지하는 것입니다. 그렇지 않으면 명령 대체가 이를 제거합니다.$0
./
z
z
find
당신이 그것을 지원하지 않는 경우 -exec … +
(OpenBSD, 나는 당신을 찾고 있습니다):
find . -depth -exec sh -c '
case $0 in ./*/*)
target="$(printf %sz "${0#./}" | tr / -)";
mv -i -- "$0" "${target%z}";;
esac
' {} \;
bash(또는 ksh93)를 사용하면 슬래시를 대시로 바꾸기 위해 외부 명령을 호출할 필요가 없습니다. 문자열 대체 구성과 함께 ksh93 매개변수 확장을 사용할 수 있습니다 ${VAR//STRING/REPLACEMENT}
.
find . -depth -exec bash -c '
for source; do
case $source in ./*/*)
source=${source#./}
target="${source//\//-}";
mv -i -- "$source" "$target";;
esac
done
' _ {} +
답변3
find . -mindepth 2 -type f -name '*' |
perl -l000ne 'print $_; s/\//-/g; s/^\.-/.\// and print' |
xargs -0n2 mv
참고: 이것은 include 에서는 작동하지 않습니다 \n
.
물론 이것은 유형 f
파일만 이동합니다.
유일한 이름 충돌은 기존에서 발생합니다.비밀번호
테스트를 위해 이 기본 하위 집합을 사용하세요.
rm -fr junk
rm -f junk*hello*
mkdir -p junk/junkier/junkiest
touch 'hello hello'
touch 'junk/hello hello'
touch 'junk/junkier/hello hello'
touch 'junk/junkier/junkiest/hello hello'
~로 이어지다
./hello hello
./junk-hello hello
./junk-junkier-hello hello
./junk-junkier-junkiest-hello hello
답변4
파일 이름 + 경로를 tr
명령에 파이프하면 됩니다.tr <replace> <with>
for FILE in `find aaa -name "*.png"`
do
NEWFILE=`echo $FILE | tr '/' '-'`
cp -v $FILE $NEWFILE
done