중복 가능성:
파일 및 디렉터리의 이름을 반복적으로 바꿉니다.
나는 다음 스크립트를 작성했습니다.
#!/bin/bash
SAVEIFS=$IFS
alias export='export'
IFS=$(echo -en "\n\b")
find $1 -name "*" -a -type f -exec sh -c let len=`expr length {}` \; -exec sh -c let str=`expr substr {} 1 len-3` \; -exec ffmpeg -y -i {} $str.mp3 \;
# restore $IFS
unalias export
IFS=$SAVEIFS
질문:
여러 셸에서 변수를 다른 셸로 내보낼 수 없다는 것을 알고 있으므로 다음이 필요합니다.
변수 사용
실행 쉘을 사용하지 마십시오
그럼 어떻게 해야 하나요?
다음 스크립트를 실행할 때:
find $1 -name "*" -a -type f -exec let len=`expr length {}` \; -exec let str=`expr substr {} 1 len-3` \; -exec ffmpeg -y -i {} $str.mp3 \;
# Note : above script doesn't has 'sh -c'
다음 오류가 발생합니다.
find: `let': No such file or directory
내보내기, 삭제export 또는 let으로 테스트했는데 -exec 내장 셸 명령에서 잘못된 점을 발견했습니다....!
어떤 아이디어가 있나요? ? ? ?
답변1
주의해야 할 몇 가지 사항이 있습니다.
큰따옴표는 변수의 내용이 셸에서 해석되지 않도록 보호합니다. IFS에는 기본적으로 "space+tab+newline"이 포함될 수 있으므로
NEWIFS=IFS
NEWIFS에 아무것도 넣지 못할 수도 있습니다.SAVEIFS="$IFS" ... IFS="$(echo -en "\n\b")" #yes, you can have " inside $( ... ) : the shell will gladly interpret them by # order of depth inside the $() construct. # A big advantage over using backquotes where it would get mixed up and almost unreadable ... IFS="$SAVEIFS"
변수 이름으로 예약어를 사용하지 마십시오(
for
let
등을 피하십시오). 또한 많은 "공통" 변수 이름(예: 등)도 피LINES
하십시오COLUMNS
.export
왜 별명인가export
? 쉘이 오래되었거나 기껏해야 쓸모가 없다면 이는 루프를 생성하는 좋은 방법처럼 보입니다.정밀도는
-name *
로 끝나는 모든 것을 피한다는 의미입니다.
.-exec sh ....
이는 서브쉘에서 시작됩니다sh
. sh가 호출 쉘로 종료되면 선언된 모든 변수는 손실됩니다.
다음과 같은 것이 필요합니다.
#!/bin/bash
for adirectory in "$@" ; do
find "$adirectory" -type f -name '*.3gp' -print | while IFS= read -r wholeline ; do
mylength=$(echo "$wholeline" | wc -c) #Not needed, just kept as exemple of a way to achieve it
myfilewithoutext="$(echo "$wholeline" | sed -e 's/.3gp$//' )"
#keeps only the filename without its ".3gp" or ".3GP" extension.
ffmpeg -y -i "$wholeline" "${myfilewithoutext}.mp3" > /dev/null #? please check if it works
done #end of the find|while
done #end of the for looping on all the arguments passed to the script (dir names)
IFS
while IFS= read -r wholeline ; do
통화 중에만 빈 문자열로 설정됩니다 read -r wholeline
. 외부는 손길이 닿지 않았습니다. 명령 매개변수는 해당 값이 일시적으로 로 설정된 VAR="something" command parameters
상태로 호출됩니다 . 여기서는 IFS를 아무것도 설정하지 않았습니다 . 여전히 한 줄씩 전달되고 비어 있으므로 전체 줄을 읽게 됩니다 .VAR
something
''
IFS
read wholeline
답변2
의견에 따르면(*.3gp를 *.mp3로 변환):
for n in *.3gp; do
ffmpeg -y -i "$n" "${n%.3gp}.mp3"
done
Olivier의 의견에 따르면 파일 이름을 이스케이프할 필요가 없는 경우(즉, 공백이나 와일드카드가 포함되지 않은 경우) 하위 디렉터리의 파일에서도 작동하며 *.3gp
. 또는 (bash에 넣어) 사용할 수 있습니다.$(find ...)
\[?*
**/*.3gp
shopt -s extglob
.bashrc