ln -s는 변수로 전달될 때 파일 이름의 일부를 제거합니다.

ln -s는 변수로 전달될 때 파일 이름의 일부를 제거합니다.

다운로드한 일부 파일을 다른 디렉터리에 연결하는 스크립트를 사용하고 있습니다. 파일 이름에 "-"가 있으면 변수가 사용 중인 로그 파일에 올바르게 기록되더라도 ln -s는 경로를 올바르게 읽지 못합니다.

for f in ${AVIFILES}
do
        BaseAviName=$(basename "$f" .avi)
        aviMp4name="'""$targetdir""/""$BaseAviName"".mp4""'"
        linkAviFile="'""$targetdir""/""$f""'"
        downloadedFile=$("'""$theFile""/""$f""'")
        ln -s "$downloadedFile" "$linkAviFile" >>$logPath 2>&1
        echo "fileIs: " "$f" ",linkAviFile is" "$linkAviFile" ",BaseAviName:" "$BaseAviName" '$aviMp4name: ' "$aviMp4name" '$downloadedFile: ' "$downloadedFile" >> "$logPath"   
done

다음의 오류 메시지는 다음과 같습니다 ln.

ln: failed to create symbolic link ‘'/home/user/Videos/TVEpisodes/Parks and Recreation/Parks.and.Recreation.S03E01.DVDRip.XviD-REWARD.avi'’ -> ‘’: No such file or directory

downloadFile 변수가 올바른 경로로 기록되더라도:

'/home/user/Downloads/Parks And Recreation - Season 3 - DVDRip-REWARD/Parks.and.Recreation.S03E01.DVDRip.XviD-REWARD.avi'

어떤 이유에서든 $downloadedFile을 ln으로 확장하여 사용하면 ln은 첫 번째 "-"부터 다음 "/"까지 파일 이름의 일부를 생략하는 것 같습니다( - Season 3 - DVDRip-REWARD ) ). 이런 일이 발생하는 타당한 이유를 찾을 수 없으며 이를 피하고 싶습니다. 어떤 제안이 있습니까?

편집: 스크립트를 다시 작성했는데 문제가 사라졌습니다. 도와주신 분들께 감사드립니다

답변1

downloadFile 변수가 올바른 경로로 기록되더라도:

'/home/user/Downloads/Parks And Recreation - Season 3 - DVDRip-REWARD/Parks.and.Recreation.S03E01.DVDRip.XviD-REWARD.avi'

이는 분명히 올바른 경로가 아닙니다. '시작과 끝에 추가 문자가 있습니다. 다음 오류 메시지에서 이를 확인할 수 있습니다 ln.

ln: failed to create symbolic link ‘'/home/user/Videos/TVEpisodes/Parks and Recreation/Parks.and.Recreation.S03E01.DVDRip.XviD-REWARD.avi'’ -> ‘’: No such file or directory

'오류 메시지의 파일 이름은 "작은따옴표" 안에 있으며 시작과 끝에 추가(ASCII 작은따옴표) 문자가 있습니다.

스크립트의 문제는 명백합니다. , 및 를 '정의할 때 추가 문자를 추가했습니다 . 그러지 마세요.aviMp4namelinkAviFiledownloadedFile

for f in "${AVIFILES[@]}"
do
    BaseAviName=$(basename -- "$f" .avi)
    aviMp4name="$targetdir/$BaseAviName.mp4"
    linkAviFile="$targetdir/$f"
    downloadedFile=$("$theFile/$f")
    ln -s -- "$downloadedFile" "$linkAviFile" >>$logPath 2>&1
    echo "fileIs: " "$f" ",linkAviFile is" "$linkAviFile" ",BaseAviName:" "$BaseAviName" '$aviMp4name: ' "$aviMp4name" '$downloadedFile: ' "$downloadedFile" >> "$logPath"   
done

껍질에소스 문법, 작은따옴표로 구분된 리터럴 문자열(예: a='hello world!'변수를 a12자 문자열로 설정 hello world!) 작은따옴표를 추가하는 경우변수로을 사용하면 작은따옴표가 표시됩니다. 14자 문자열로 a="'hello world!'"설정 됩니다 .a'hello world!'

쉘 스크립트에서 따옴표를 사용할 때 기억해야 할 핵심은 변수 확장 주위에 큰따옴표를 두는 것입니다(예: ) ln -s -- "$downloadedFile" "$linkAviFile". 이와 같은 코드는 ln -s -- $downloadedFile $linkAviFile변수 값을 공백 문자 downloadedFile로 분할 linkAviFile하고 각 부분을 와일드카드 패턴으로 해석합니다. 이러한 큰따옴표는 쉘의 소스 구문의 일부이며 파서에 의해 해석됩니다. 변수 값에 따옴표를 넣어도 아무 문제가 해결되지 않습니다.

또한 파일 이름이 로 시작하면 -명령은 이를 옵션으로 해석합니다. 이를 방지하려면 변수에 파일 이름이 있는 경우 모든 옵션 뒤와 모든 파일 이름 앞에 인수를 명령에 전달하십시오. 예를 들어 파일 이름이 다음으로 시작하지 않는 것이 확실한 경우 알고 있으면 --yes를 생략할 수 있습니다. ) 절대 경로). 이는 "이후에는 더 이상 옵션이 없습니다"를 의미합니다.-----

${AVIFILES}따옴표가 없는 다른 확장과 마찬가지로 변수 값을 공백으로 나눕니다 . 여러 파일 이름을 변수에 저장하려면 문자열 대신 배열로 만드세요. 이렇게 하려면 ksh, bash 또는 zsh가 필요하며 일반 sh에서는 작동하지 않습니다.

AVIFILES=(foo.avi bar.avi "file name with spaces.avi")

관련 정보