Bash 스크립트에서 (전달된) 변수로 cd할 수 없습니다.

Bash 스크립트에서 (전달된) 변수로 cd할 수 없습니다.

나는 bash를 사용하여 audacious에서 conky까지의 일부 정보를 표시용(앨범 아트 포함)으로 가져오고 있습니다. 나는 audacious에서 음악 파일의 디렉토리 경로를 얻은 다음 해당 디렉토리로 CD를 이동하여 폴더.jpg를 찾으려고 시도합니다. 발견되면 표시할 준비를 합니다. 불행하게도 '잘 구성된' 경로 이름에는 의존할 수 없습니다. 그들 중 누구도 터미널에서 문제가 없지만 bash가 수행하는 평가는... 현재 설정이 처리하는 것처럼 보이지만 두 배의 공백( ) ' / 및 아마도 다른 것에서 질식합니다. 관련 기능은 다음과 같습니다.

GetArt ()
{
    file_path=`audtool --current-song-tuple-data file-path` # get the path to the song
    file_path=$(eval echo "${file_path}")                   # pre-expand to full path
    cd "${file_path}"
    if [[ ! -e "folder.jpg" ]];                             # if no art work found
    then
        cp ~/Work/vinyl.png /tmp/cover.png              # put in placeholder
    else
        convert "${file_path}""/folder.jpg" -resize 120x120 /tmp/cover.png # ready for showing
    fi
}

어떤 아이디어가 있습니까? 아니면 와이어 브러시를 꺼내서 'C' 컴파일러에서 녹을 제거하는 것이 더 쉬울까요?

나는 큰따옴표, 작은따옴표, 역따옴표 및 심지어 다음과 같은 구성을 사용해 보았습니다.

code=$code \"\$filename\""

하지만 아직 아무것도 제대로 작동하지 않는 것 같습니다. 다행스럽게도 "예술을 찾을 수 없음" 대체 사진이 대신 팝업되기 때문에 '예쁘게' 실패하지만 때로는 다음 노래나 앨범까지 표준 오류 전체에서 트림이 발생하는 경우도 있습니다.

답변1

file_path="${file_path/#~/$HOME}"확장하여 사용할 수 있습니다.단지.~

내가 말할 수있는 한,물결표 확장의 출력에 대해 수행해야 하는 유일한 종류의 확장입니다 audtool --current-song-tuple-data file-path. 또한 물결표 표기의 특정 사례는 하나만 나타납니다. Audacious가 사용하는 경로가 Audacious를 실행하는 사용자의 홈 디렉터리로 시작하는 경우 경로의 해당 부분은 의 ~출력에서 ​​로 대체됩니다 audtool. 이후audacious그리고audtoolaudtool맨페이지에서는 이를 명확히 설명하지 않고 물결표 확장 형식 이 접두어로 붙은 출력 경로에 접근하려고 시도했지만 ~username다행히도 그렇게 하지 않는 것 같습니다. 제가 "다행히"라고 말한 이유는 상황이 매우 간단하다는 뜻이기 때문입니다.

해당 명령의 출력에서 ​​수행해야 하는 유일한 변환은 선행 부분을 사용자의 홈 디렉터리 경로로 audtool바꾸는 것이므로 해당 확장 자체를 수행하는 코드를 스크립트에 작성하고 그렇지 않으면 경로를 수정하지 않은 채로 남겨둘 수 있습니다. ~. 재생할 수 있는 오디오 파일의 파일 이름에는 셸에서 특별히 처리되는 문자가 포함될 수 있으며,다른 사람이 이름을 붙인 파일을 재생하면보안 취약점을 야기할 수도 있습니다.귀하의 스크립트에서. 셸에서 신뢰할 수 없는 임의의 텍스트를 실행하거나 확장하지 않음으로써 해당 문제를 완전히 피할 수 있습니다.

자신을 확장하는 방법에는 여러 가지가 있습니다 ~. 나는 제안한다:

file_path="$(audtool --current-song-tuple-data file-path)"  # might need tilde expansion
file_path="${file_path/#~/$HOME}"  # do the tilde expansion, if needed

이는 필요할 수 있는 하나의 변환을 수동으로 수행합니다. 특히 의 출력이 audtool로 시작 하면 ~변수 값을 확인하여 얻은 사용자의 홈 디렉터리로 대체됩니다 HOME. 출력이 로 시작하지 않으면 ~확장이 수행되지 않습니다.

${file_path/#~/$HOME}이 접근 방식 은~ 아니다모든 형태의 물결표 확장을 시뮬레이션하기 위한 시도로 사용된 경우 해당 ~username형식(및 기타 더 모호한 형식)에서 잘못된 대체를 수행할 수 있기 때문에 정확합니다. 그러나 출력의 경로가 audtool현재 사용자의 홈 디렉터리를 지정하는 간단한 경우에만 물결표 표기법을 사용하는 한(나는 이것이 사실이라고 생각합니다) 이 접근 방식은 다음과 같습니다.~이다해당 경로에 적합하고 정확합니다.

작동 방식은 다음과 같습니다.

  • 일반적으로,Bash가 확장됩니다 ${parameter/pattern/string}의 값으로 들어가 parameter지만,일치하는 부분pattern로 대체되었습니다 string. 패턴과 일치하는 부품이 없으면 정확한 값이 parameter사용됩니다.
  • pattern가 앞에 로 쓰여 지면 #값의 맨 처음부터만 일치할 수 있습니다 parameter. ( #이 위치에는 의미 있는 다른 문자가 있습니다 . a는 %바로 그 위치에서 패턴이 일치해야 합니다., a는 /패턴이 최대 한 번이 아니라 나타나는 횟수만큼 일치하고 교체되도록 합니다.)
  • ~패턴에 특별한 의미가 없으므로 문자 그대로 일치하고 대체할 문자로 처리됩니다.

보다매개변수 확장자세한 내용은.

내가 작성한 코드는 audtool현재 재생 중인 노래가 없을 때(또는사이먼 서들러(Simon Sudler)가 언급됨, 오류가 있는 경우). 그러나 빈 출력에서 ​​중단되거나 후속 처리를 방해하지 않습니다. 따라서 해당 사건을 다루고 싶다면 여전히 가능합니다.

마지막으로, 귀하의 사용 사례에 중요하지 않다고 생각되는 두 가지 차이점을 얼버무렸다는 점을 언급하고 싶습니다.

  1. audtool경로는 Audacious에서 왔기 때문에 Audacious를 한 사용자로 실행하고 다른 사용자로 실행하는 이상한 상황을 시도하고 어떻게든 작동하도록 D-Bus를 구성했다면 다른 사용자를 참조하는 audtool데 신경을 써야 합니다. ~스크립트를 실행하는 사용자가 아닌 사용자의 홈 디렉터리입니다.
  2. 기술적으로 말하면, 현재 사용자에 대한 물결표 확장(쉘에서 ~자체적으로 발생하거나 바로 다음에 /)이 발생하지 않습니다.상당히에 해당합니다 "$HOME". 쉘은 HOME설정되지 않은 이상한 경우를 처리하려고 시도할 수 있습니다 . Bash는 이를 처리하려고 시도하고 여전히 올바른 확장을 생성합니다. 하지만 당신이 이 목적을 위한 구별에 관심이 있는지 의심스럽습니다. 보다물결표 확장자세한 내용은.

답변2

변수를 다시 할당할 file_path필요는 없습니다. 스크립트가 중단될 수 있는 2가지 징후가 발생할 수 있습니다.

  1. audtool반환값이 오류 이므로 변수가 비어 있습니다.
  2. audtools공백이 포함된 디렉터리를 반환합니다 .
  3. audtool~홈 디렉토리에 포함

다음은 이러한 문제를 해결하는 방법에 대한 제안입니다.

GetArt ()
{
    file_path="$(audtool --current-song-tuple-data file-path)"
    file_path="$(readlink -f "$(bash -c "echo $file_path")")"
    if [[ ! -d $file_path ]]; then
        echo "error: $file_path does not exists"
        exit 1
    fi
    folder_jpg="$file_path/folder.jpg"
    if [[ ! -e "$folder_jpg" ]]; then
        cp ~/Work/vinyl.png /tmp/cover.png
    else
        convert "$folder_jpg" -resize 120x120 /tmp/cover.png
    fi
}

"$(command)"폴더 이름의 공백(있는 경우)을 처리합니다 . cd필요하지 않은 경우 스크립트 내부에서 사용하지 마십시오 . 반환 문자열이 디렉터리인지 확인하는 것은 항상 좋은 생각입니다. 대부분의 경우 절대 경로를 사용하는 것이 더 좋으며 잘못된 폴더에서 명령이 실행되는 것을 방지합니다.

~Bash 확장 에 대한 참고 사항 :

확장은 ~bash에 의해 처리되므로 readlink -f여기서는 도움이 되지 않습니다. 따라서 ~확장하려면 따옴표 없이 실행되어야 합니다(스크립트를 업데이트했습니다). 물론 이것은 한 줄로 처리될 수 있습니다.

# expansion from current bash
$ set -x; readlink -f ~; set +x
+ readlink -f /home/user
/home/user
+ set +x

# expansion will not work, with quoted ~
$ set -x; readlink -f '~'; set +x
+ readlink -f '~'
/home/user/~
+ set +x

# expansion from un-quoted ~ with sub-shell
$ set -x; readlink -f "$(bash -c "echo ~")"; set +x
++ bash -c 'echo ~'
+ readlink -f /home/user
/home/user
+ set +x

관련 정보