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