while 루프 중 "cp: 대상 '...'은(는) 디렉터리가 아닙니다."

while 루프 중 "cp: 대상 '...'은(는) 디렉터리가 아닙니다."

이름을 단축하고 싶은 파일 디렉터리가 있습니다.

(3) andrew@andrew Learning_Plans $ ls -al
total 580
drwxr-xr-x 2 andrew andrew  4096 Apr 10 21:40 .
drwxr-xr-x 7 andrew andrew  4096 Apr 10 16:46 ..
-rw-rw-rw- 1 andrew andrew 17825 Mar 25 14:18 Edexcel International GCSE Physics Chapter 10 Properties of Waves Learning Plan.docx
-rw-rw-rw- 1 andrew andrew 18472 Mar 25 14:19 Edexcel International GCSE Physics Chapter 11 The Electromagnetic Spectrum Learning Plan.docx
-rw-rw-rw- 1 andrew andrew 18692 Mar 25 14:19 Edexcel International GCSE Physics Chapter 12 Light Waves Learning Plan.docx
:
etc

명령줄에서 다음 명령을 실행했습니다.

while read x; do echo cp \'$x\' $(echo $x | cut -b38- | tr ' ' '_'); done < <(find . -type f)

이것은 내가 기대하는 것을 생산합니다.

cp './Edexcel International GCSE Physics Chapter 17 Energy Resources and Electricity Generation Learning Plan.docx' Chapter_17_Energy_Resources_and_Electricity_Generation_Learning_Plan.docx
cp './Edexcel International GCSE Physics Chapter 19 Solids, Liquids and Gases Learning Plan.docx' Chapter_19_Solids,_Liquids_and_Gases_Learning_Plan.docx
cp './Edexcel International GCSE Physics Chapter 28 Cosmology Learning Plan.docx' Chapter_28_Cosmology_Learning_Plan.docx
:
etc

하지만, 에코를 제거하면 다음이 제공됩니다.

cp: target ‘Chapter_17_Energy_Resources_and_Electricity_Generation_Learning_Plan.docx’ is not a directory
cp: target ‘Chapter_19_Solids,_Liquids_and_Gases_Learning_Plan.docx’ is not a directory
cp: target ‘Chapter_28_Cosmology_Learning_Plan.docx’ is not a directory
:
etc

파일 이름의 공백과 관련이 있는 것 같은데 작은 따옴표로 문제를 해결할 수 있을까요?

echo의 출력을 다시 터미널에 복사/붙여넣기를 시도했는데 제대로 작동했습니다! while 루프에서는 실행되지 않습니다.

버전:

(3) andrew@andrew Learning_Plans $ bash --version
GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
(3) andrew@andrew Learning_Plans $ cat /etc/*release
DISTRIB_ID=LinuxMint
DISTRIB_RELEASE=17.3
DISTRIB_CODENAME=rosa
DISTRIB_DESCRIPTION="Linux Mint 17.3 Rosa"
NAME="Ubuntu"
VERSION="14.04, Trusty Tahr"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 14.04 LTS"
VERSION_ID="14.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"

답변1

문제는 파일 이름의 공백입니다. 파일 이름은 공백으로 구분됩니다. cp세 개 이상의 매개변수를 가져오는 경우 마지막 매개변수는 디렉터리여야 합니다. 그렇지 않아서 불평을 합니다.

Edexcel International GCSE Physics안전한 방법으로 각 파일 이름에서 문자열을 제거 하고 공백을 밑줄로 변환하려면 (in bash)을 사용하십시오.

for name in 'Edexcel International GCSE Physics '*.docx; do
    newname=${name#Edexcel International GCSE Physics }
    newname=${newname// /_}

    mv -i "$name" "$newname"
done

그러면 현재 디렉터리의 모든 관련 파일을 반복하고 newname먼저 이름 시작 부분에서 알려진 하위 문자열을 제거한 다음 나머지 공백을 밑줄로 변환하여 변수에 새 이름을 만듭니다. 그런 다음 이전 이름을 새 이름으로 바꿉니다.

코드에서와 같이 파일의 복사본을 만들고 싶다면 로 변경하세요 mv.cp

시험:

$ ls
Edexcel International GCSE Physics Chapter 10 Properties of Waves Learning Plan.docx
Edexcel International GCSE Physics Chapter 11 The Electromagnetic Spectrum Learning Plan.docx
Edexcel International GCSE Physics Chapter 12 Light Waves Learning Plan.docx

(여기서 루프가 실행됩니다)

$ ls
Chapter_10_Properties_of_Waves_Learning_Plan.docx
Chapter_11_The_Electromagnetic_Spectrum_Learning_Plan.docx
Chapter_12_Light_Waves_Learning_Plan.docx

이 함수를 여러 하위 디렉터리에 반복적으로 적용하시겠습니까?

find . -type f -name 'Edexcel International GCSE Physics *.docx' -exec sh -c '
    for pathname; do
        name=$(basename "$pathname")

        newname=${name#Edexcel International GCSE Physics }
        newname=${newname// /_}

        mv -i "$pathname" "$(dirname "$pathname")/$newname"
    done' sh {} +

관련된:

관련 정보