명령줄에서 URL을 입력으로 사용하거나 입력이 제공되지 않으면 내부 목록을 사용하는 yt-dlp용 셸 스크립트를 만들려고 합니다. 입력이 주어지면 스크립트가 작동하지만 입력이 주어지지 않으면 충돌이 발생하므로 내부 목록을 사용합니다.
#!/usr/bin/env bash
URLfromTerminal="$1"
PathToList="--batch-file '${HOME}/bin/ytdlp/Lists/Test.txt'"
[[ -z "$URLfromTerminal" ]] && Download="$PathToList" || Download="$URLfromTerminal"
yt-dlp -ciw \
-S "res:1920" \
--ffmpeg-location "$HOME"/bin/ffmpeg/ffmpeg \
"$Download"
입력이 제공되지 않고 내부 목록이 사용될 때 오류 메시지:
yt-dlp: error: no such option: --batch-file '/Users/UserName/bin/ytdlp/Lists/Test.txt'
변수에서 확장할 때 yt-dlp가 텍스트 파일 경로를 옵션으로 간주하는 이유는 무엇입니까?
저는 쉘 스크립팅을 처음 접했고 모범 사례가 무엇인지 모르기 때문에 일반적인 개선도 환영합니다.
답변1
귀하의 질문에는 두 가지 측면이 있습니다.
- 파일 이름을 보유하는 것으로 간주되는 문자열에 리터럴 따옴표를 포함합니다. 따옴표는 파일 이름의 일부가 아니므로 문자열에 포함되어서는 안 됩니다.
--batch-file
파일 경로 이름이 포함된 문자열에 이 옵션을 포함할 수 있습니다. 이렇게 하면 인용되지 않은 변수 확장을 적절하게 분할하기 위해 쉘에 의존하게 됩니다. 인용한 확장으로 인해$Download
쉘은 문자열을 분할하지 않으며 전체 문자열이 단일 인수로 사용됩니다.
#!/bin/sh
if [ -n "$1" ]; then
printf '%s\n' "$1"
else
cat ~/bin/ytdlp/Lists/Test.txt
fi |
yt-dlp -ciw \
-S res:1920 \
--ffmpeg-location ~/bin/ffmpeg/ffmpeg \
-a -
이는 첫 번째 매개변수가 비어 있는지 확인하기 위해 간단한 테스트를 사용합니다 -n
. 비어 있지 않으면 printf
(same as) 을 사용하여 읽을 대상 으로 전달합니다 yt-dlp
. 비어 있으면 텍스트 파일이 전달됩니다.-a -
--batch-file -
yt-dlp
cat
시도하는 것과 더 유사한 방식으로 문제를 해결하십시오.
#!/bin/sh
if [ -z "$1" ]; then
set -- -a ~/bin/ytdlp/Lists/Test.txt
fi
yt-dlp -ciw \
-S res:1920 \
--ffmpeg-location ~/bin/ffmpeg/ffmpeg \
"$@"
이는 비어 있지 않은 yt-dlp
경우 스크립트의 인수 목록을 전달합니다 . $1
그렇지 않으면 사용하기 전에 인수 목록을 -a
텍스트 파일의 경로 이름 으로 설정합니다.저것통화 yt-dlp
.
이렇게 하면 스크립트의 명령줄에 URL뿐만 아니라 원하는 만큼의 추가 인수를 전달할 수 있습니다.
답변2
당신이 인용한 내용을 보세요! 두 개의 매개변수 문자열을 전달하려고 합니다.
--batch-file
그리고
'/Users/UserName/bin/ytdlp/Lists/Test.txt'
주장으로는,
"--batch-file '/Users/UserName/bin/ytdlp/Lists/Test.txt'"
예를 들어, yt-dlp는 호출 매개변수에 대해 알고 있지만(즉, 매개변수 문자열을 해석하는 방법을 알고 있지만) --batch-file
그렇지 --help
않습니다 --batch-file '/Users/UserName/bin/ytdlp/Lists/Test.txt'
.
마지막 줄은 감싸지 않았습니다 "
.$Download
답변3
일반적으로더 안전하고 더 나은도착하다쉘 변수 인용. 그러나 이 경우 따옴표 "--batch-file '${HOME}/bin/ytdlp/Lists/Test.txt'"
는 플래그 및 해당 값이 아닌 단일 인수로 전달되므로 스크립트를 손상시키는 것은 따옴표입니다 . 임의의 파일 이름을 사용할 수 있는 가장 간단한 솔루션은 옵션이 아닌 변수에 경로를 입력하는 것입니다.
#!/usr/bin/env bash
URLfromTerminal="$1"
PathToList="$HOME/bin/ytdlp/Lists/Test.txt"
if [[ -z "$URLfromTerminal" ]]; then
DownloadFlag="--batch-file"
DownloadPath="$PathToList"
else
DownloadPath="$URLfromTerminal"
fi
yt-dlp -ciw \
-S "res:1920" \
--ffmpeg-location "$HOME"/bin/ffmpeg/ffmpeg \
"$DownloadFlag" "$DownloadPath"
비어 있으면 $DownloadFlag
단순히 빈 문자열로 전달되므로 명령은 계속 작동합니다.
공백이 포함된 매개변수를 전달하는 안전한 표준 방법은 배열을 사용하는 것입니다. 따라서 더 복잡한 경우에는 다음이 필요하므로 해당 옵션도 살펴보는 것이 좋습니다.
#!/usr/bin/env bash
URLfromTerminal="$1"
PathToList="$HOME/bin/ytdlp/Lists/Test.txt"
if [[ -z "$URLfromTerminal" ]]; then
DownloadPath=( "--batch-file" "$PathToList")
else
DownloadPath=( "$URLfromTerminal" )
fi
yt-dlp -ciw \
-S "res:1920" \
--ffmpeg-location "$HOME"/bin/ffmpeg/ffmpeg \
"${DownloadPath[@]}"