파일에서 복사 명령 실행

파일에서 복사 명령 실행

DE_CopyOldToNew.txt이전 파일 이름을 새 파일 이름으로 복사하기 위한 여러 복사 명령이 포함된 파일이 있습니다 .

파일에는 다음과 같은 줄이 포함되어 있습니다.

cp /migrationfiles/Company\ Name\ GmbH/2014.138_Old\ File\ Name.pdf /appl/data/docs/202403/DE_2014.138_NewFile_1.pdf
cp /migrationfiles/Company\ Name\ GmbH/2014.139_Old\ File\ Name.pdf /appl/data/docs/202403/DE_2014.139_NewFile_1.pdf

내 쉘 스크립트에서는 각 줄을 반복하여 실행합니다.

echo "Start!"
while read -r line
do
  command "$line"
done < /tmp/DE_CopyOldToNew.txt

스크립트를 실행할 때 읽은 각 줄에 대해 다음을 얻습니다.

 : No such file or directory6: cp /migrationfiles/Company\ Name\ GmbH/2014.138_Old\ File\ Name.pdf /appl/data/docs/202403/DE_2014.138_NewFile_1.pdf

프롬프트에서 수동으로 행을 실행하면 오류 없이 잘 작동합니다...

답변1

문제는 전체 줄을 다음과 같이 읽는다는 것입니다.하나쉘 변수를 line선택한 다음 따옴표를 사용하십시오(예: as "$line").

쉘 변수로 작업할 때, 특히 공백이나 기타 "문제가 있는" 문자가 포함된 파일 이름을 처리할 때 큰따옴표는 일반적으로 정확하지만, 이 경우에는 다음을 의미합니다.전선cp명령어로 구성그리고 그 주장명령문에서 단일 쉘 토큰으로 처리됩니다 command.

이는 루프에서 cp인수 가 /migrationfiles/Company\ Name\ GmbH/2014.138_Old\ File\ Name.pdf있는 명령을 실행하지 않고 /appl/data/docs/202403/DE_2014.138_NewFile_1.pdf쉘이 다음과 같은 실행 파일을 실행하려고 시도하고 있음을 의미합니다.

cp /migrationfiles/Company\ Name\ GmbH/2014.138_Old\ File\ Name.pdf /appl/data/docs/202403/DE_2014.138_NewFile_1.pdf

명령과 인수를 구분하는 데 사용되는 공백은 명령 이름의 일부로 해석됩니다. 물론 이 실행 파일은 존재하지 않습니다.

당신이 할 수 있는 일은 이 줄을 다음과 같은 세 가지 변수로 읽는 것입니다.

echo "Start!"
while read cmd arg1 arg2
do
  command "$cmd" "$arg1" "$arg2"
done < /tmp/DE_CopyOldToNew.txt

구조는 항상 예에 표시된 형식을 취한다고 가정합니다.

노트read명령확실히-r옵션은 다음 공백이 이스케이프 문자로 해석되는 것을 비활성화하기 때문에 포함되었습니다 \. 그러나 여기서 이 작업을 수행하려면 셸이 필요합니다.

답변2

당신은 말한다,

DE_CopyOldToNew.txt이전 파일 이름을 새 파일 이름으로 복사하기 위한 여러 복사 명령이 포함된 파일이 있습니다 .

...그리고 당신은 이 명령을 실행하고 싶다고 말했습니다 cp.

운이 좋다. 쉘에 의해 순서대로 실행되는 명령 세트가 포함된 파일인 쉘 스크립트가 있기 때문이다. 여러분이 해야 할 일은 쉘이 스크립트에 있는 명령을 실행하도록 하는 것뿐입니다.

sh DE_CopyOldToNew.txt

그러면 기본 셸이 시작되고 sh파일 내용을 명령별로 실행하게 됩니다.

답변3

TXT 파일이 아무 것도 하도록 하지 않고 이를 데이터 소스로 취급하므로 스크립트를 사용하여 수행해야 할 작업을 수행할 뿐만 아니라 데이터에 대한 제어로도 사용할 수 있습니다.

# Read each line of the file
while IFS= read -r line; do
    # Get the files using awk with ' /' as separator.
    # $line could have escaped spaces with '\ ' so we use parameter substitution →
    # → to substitute them to unescaped spaces: "${line//\\ / }".
    source_file=$(awk -F' /' '{ print "/"$2 }' <<<"${line//\\ / }") # source file
    destination=$(awk -F' /' '{ print "/"$3 }' <<<"$line") # destination
    
    # For example you can control that the source file exists
    if [[ ! -f "$source_file" ]]; then
        echo "The file $source_file does not exists!"
        exit
    fi
    
    # The cp command is executed here
    cp "$source_file" "$destination"
done </tmp/DE_CopyOldToNew.txt

관련 정보