찾기 출력을 구문 분석하여 배쉬 이동 및 이름 바꾸기 추출하고 싶습니다. 내 파일은 다음과 같습니다 ./path1/pathA/fileI.pdf ./path1/pathB/fileII.pdf 나는

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은 단순히 자리 표시 자입니다. $0bash 규칙에 따라에 할당 된 것은 우리가 실행하는 명령의 이름입니다.

  • 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