pdf 파일의 중첩 디렉토리가 있으며 다음과 같이 이름을 바꾸는 상위 레벨 디렉토리로 추출하고 싶습니다.
내 파일은 다음과 같습니다
./path1/pathA/fileI.pdf
./path1/pathB/fileII.pdf
나는 달성하고 싶다 :
./path1_pathA_fileI.pdf
./path1_pathB_fileII.pdf
나는 그렇게함으로써 파일 목록을 만들 수 있다는 것을 알고있다.
find . -type f -name "*.pdf"
그리고 나는 다음을 사용하여 해결책을 상상할 수 있습니다.
find . -type f -name "*.pdf" | mv -t ...
그러나 나는 bash에서 구문 분석과 변수 할당을 이해하지 못하기 때문에 어떻게 채우는 지 모른다. ‘/’에서 경로를 어떻게 분할하고 위와 같이 새로운 경로와 파일 이름을 형성합니까?
미리 감사드립니다!
답변
시험:
find . -mindepth 2 -type f -name '*.pdf' -exec bash -c 'f=${1#./}; mv "$1" "./${f//\//_}"' None {} \;
이것은 모든 파일 이름, 심지어 이름에 개행 문자가있는 파일에도 안전합니다.
작동 원리
-
-mindepth 2
이것은 현재 디렉토리에 이미있는 파일을 처리하지 않도록 지시합니다.
-
-type f -name '*.pdf'
이렇게하면
pdf
확장자 가있는 일반 파일로 검색이 제한 됩니다. -
-exec bash -c '...' None {} \;
파일 이름을 첫 번째 인수로 제공하는 따옴표 붙은 문자열에서 명령을 실행합니다
$1
.우리의 목적을 위해 문자열
None
은 단순히 자리 표시 자입니다.$0
bash 규칙에 따라에 할당 된 것은 우리가 실행하는 명령의 이름입니다. -
f=${1#./}; mv "$1" "./${f//\//_}"
이렇게하면 (a)
./
파일 이름에서 접두사 가 제거 되고 (b) 파일이 새 이름으로 원하는 위치로 이동합니다.${1#./}
bash의 접두사 제거 예제입니다 . 처음부터 제거 된 스트 린$1
을 반환합니다./
.${f//\//_}
bash의 패턴 대체 예입니다 . 문자열$f
이 모두/
로 대체 된 문자열 을 반환합니다_
. 이러한 기능에 대한 자세한 내용을 읽으려면의 섹션을 참조man bash
라는 제목 매개 변수 확장을 .
보다 효율적인 버전
위의 버전은 발견 된 모든 파일에 대해 bash를 호출합니다. 또는 발견 된 여러 파일에 대해 bash를 한 번만 호출 할 수 있습니다. 이를 위해 명령을 for
루프로 묶습니다.
find . -mindepth 2 -type f -name '*.pdf' -exec bash -c 'for f in "$@"; do f=${f#./}; echo mv "$f" "./${f//\//_}"; done' None {} +
대체 문제
우리가 원하는 모든 파일이 두 번째 수준의 디렉토리에 있고 우리가 이동 된 파일을 대신하도록 반전 디렉토리 이름의 순서를 갖고 싶어한다고 가정 ./path1_pathA_fileI.pdf
, 우리가 끝을 ./pathA_path1_fileI.pdf
. 이 경우 :
for d1 in */; do d1=${d1%/}; for d2 in "$d1"/*/; do d2=${d2%/}; p="${d2#$d1/}_$d1"; for f in "./$d2"/*.pdf; do echo mv "$f" "./${p}_${f#./$d2/}"; done; done; done
또는 자신의 명령을 선호하는 사람들은 여러 줄로 퍼져 있습니다.
for d1 in */
do
d1=${d1%/}
for d2 in "$d1"/*/
do
d2=${d2%/}
p="${d2#$d1/}_$d1"
for f in "./$d2"/*.pdf
do
echo mv "$f" "./${p}_${f#./$d2/}"
done
done
done