약간의 조작 끝에 나는 행복하게 실행할 수 있는 명령이 포함된 파일을 얻었습니다.
입력 파일(파일 이름은 inp2.txt):
"02 - Beautiful Emptiness.mp3"
"02 - Come. mp3"
"02 - Go For It.mp3"
암호:
#!/bin/bash
exec 4<inp2.txt # opening file via descriptor
while read LINE <&4; do
printf "%s\n" "$LINE" # just to watch that command is proper
$LINE # execute command
done
편집하다:죄송합니다. 이해하는 데 중요하지 않다고 생각되는 중요한 코드 부분을 생략했습니다. 전체 코드:
#!/bin/bash
IFS='
'
declare LINE
declare BUF
declare a
a=1
rm inp2.txt # delete previous version of file
exec 3< inp.txt # open descriptor for a file()content of it is written above
while read LINE <&3; do # read it
printf "mv ""$LINE"" %s\n" """$a"".mp3" >> inp2.txt
# form a command and output it to the file, just to make sure that I got a command that I really want
let "a++" # increment number that will be a part of new unique name
done
exec 4<inp2.txt #open again descriptor with ready commands
while read LINE <&4; do
printf "%s\n" "$LINE" # check again
$LINE # here it should be executed, but I get mistakes that is pointed down
done
exit 0
산출:
명령은 맞는 것 같은데 뭔가 잘못되어 정확히 무엇이 잘못되었는지 알 수 없습니다.
답변1
게시한 스크립트, 데이터 파일 및 출력이 일치하지 않습니다. 스크립트나 데이터 파일은 모두 포함되어 있지 않지만 mv
스크린샷은 포함되어 있습니다. 또한 귀하의 스크린샷에는 귀하가 게시한 스크립트에 없는 28행이 언급되어 있습니다. 일관되지 않은 정보를 제공하면 문제를 정확히 파악하기가 어렵습니다.
즉, 두 가지 중 하나를 수행하려고 하는데 어느 것도 원하는 대로 작동하지 않습니다.
입력 파일에 다음과 같은 줄이 포함되어 있는 경우
mv "02 - Beautiful Emptiness.mp3" 1.mp3
글쎄, 그것은 실제로 쉘 스크립트입니다. 한 줄씩 읽는 대신 쉘 스크립트로 실행하십시오.
rm -rf ~
해당 파일을 포함하여 파일의 모든 항목을 실행할 것이므로 이 파일을 신뢰할 수 있는지 확인하십시오 .. inp2.sh
입력 파일에 다음과 같은 줄이 포함되어 있는 경우
"02 - Beautiful Emptiness.mp3"
그러면 읽는 방식이 작동하지 않습니다.
read LINE
다음을 수행하십시오.- 한 줄을 읽으십시오;
- 줄이 백슬래시로 끝나면 백슬래시를 제거하고 다른 줄을 읽습니다(
\
a로 끝나지 않는 줄을 읽을 때까지 반복). - 모든 백슬래시+문자 시퀀스를 두 번째 문자로만 바꿉니다.
LINE
줄 바꿈을 빼고 읽은 줄의 연결로 설정됩니다 .
쉘이 command 를 실행할 때
$LINE
따옴표 밖의 변수 대체를 볼 때 항상 수행하는 작업을 수행합니다.- 변수의 값을 공백이 포함된 각 위치의 단어 목록으로 분할합니다(기본값은 이라고 가정
IFS
). - 각 단어를 전역 패턴으로 처리하고 하나 이상의 파일과 일치하면 확장합니다.
쓸모없는 것 같나요? 이것은. 여기에는 따옴표에 대한 내용이 없다는 점에 유의하십시오. 따옴표는 셸 확장 규칙의 일부가 아니라 셸 구문의 일부입니다.
inp2.txt
한 줄에 하나씩 파일 이름 목록을 포함해야 합니다 . 바라보다"IFS=;" 대신 "IFS= 읽기"가 자주 사용되는 이유는 무엇입니까?파일에서 줄 목록을 읽는 방법을 알아보세요. 당신은 다음과 같은 것을 원할 것입니다
i=1
while IFS= read -r source; do
dir=$(dirname -- "$source")
ext=
case "${source##*/}" in
*.*) ext=.${source##*.};;
esac
mv -- "$source" "$dir/$i$ext"
done <inp2.txt
완전성을 기하기 위해 또 다른 가능성을 언급하겠지만 지루하고 하려는 것처럼 보이는 일을 할 수 없게 되므로 권장하지 않습니다. 이와 같은 파일
"02 - Beautiful Emptiness.mp3" "02 - Come. mp3" foo\ bar.mp3
그런 다음 명령을 통해 읽을 수 있습니다 xargs
. 입력은 xargs
공백으로 구분된 요소 목록으로, 작은따옴표로 묶인 리터럴(공백을 포함할 수 있음), 큰따옴표로 묶인 리터럴(공백을 포함할 수 있음) 또는 백슬래시 이스케이프 문자가 없는 리터럴일 수 있습니다. 텍스트( \
다음 문자 인용). 이 xargs
구문은 셸이 인식할 수 있는 구문과 다릅니다.
답변2
겉보기에는 인용에 문제가 있는 것 같습니다.
"명령 실행" 줄에서 이를 따옴표로 묶으 면 해당 명령은 일부 추가 매개변수가 있는 명령이 "$LINE"
아닌 단일 명령으로 처리됩니다 . mv
따라서 우선 해당 줄에서 따옴표를 제거해야 합니다.
또한 경로에 문제가 있습니다. 파일 이름에 공백이 있는 것 같습니다. 따라서 inp2.txt 파일을 수정하여 공백이 있는 경로/파일 이름 주위에 따옴표를 추가하거나 공백을 이스케이프 처리해야 합니다.
또한 스크립트 상단에 다음을 추가해 볼 수도 있습니다.
IFS='
'
예, 두 번째 줄은 해당 줄에 대한 작은따옴표입니다. 그러면 스크립트에서 공백이 처리되는 방식이 변경됩니다.
스크립트는 다음과 같습니다.
#!/bin/bash
IFS='
'
exec 4<inp2.txt # opening file via descriptor
while read LINE <&4; do
printf "%s\n" "$LINE" # just to watch that command is proper
$LINE # execute command
done
답변3
이 버전은 명령줄을 작성하고 이를 bash에 입력하여 실행하는 방식으로 작동합니다.
#! /bin/bash
i=1
while read LINE ; do
# strip off any leading or trailing double-quotes.
# script now works whether input quotes the filenames or not.
LINE=$(echo "$LINE" | sed -r -e 's/^"|"$//g')
[ -n "$LINE" ] && echo mv \"$LINE\" \"$i.mp3\"
i=$((i + 1))
done < inp2.txt | bash
참고: 스크립트를 파일럿 테스트하려면 | bash
마지막 줄을 제거하거나 으로 변경하세요 | cat
. 그러면 다음과 같은 출력이 생성됩니다.
mv "02 - Beautiful Emptiness.mp3" "1.mp3"
mv "02 - Come. mp3" "2.mp3"
mv "02 - Go For It.mp3" "3.mp3"
이 [ -n "$LINE" ]
테스트는 입력에서 빈 줄을 건너뜁니다. 내가 만든 inp2.txt의 끝에 추가 빈 줄이 있기 때문에 추가되었습니다.
답변4
이런 것을 시도해 보셨나요?
while read LINE <&4; do
printf "%s\n" "$LINE" # just to watch that command is proper
comm="$LINE" # asssign command to a variable
$comm # execute command
done
bash를 사용하면 저에게 효과적입니다.