저는 명령줄 인수에서 디렉터리를 읽고 ls
이에 대한 작업을 수행하는 bash 스크립트를 작성 중입니다.
간단한 디렉토리를 지정하면 모든 것이 정상입니다.
하지만 비슷한 작업을 수행하고 싶기 때문에 이라는 변수에 저장된 값을 /home/{x,y}
사용하여 스크립트가 호출됩니다 .my-script -d '/home/{x,y}'
'/home/{x,y}'
source
시도했지만
ls "${source}"
돌아왔습니다.ls: cannot access /home/{x,y}: No such file or directory
시도해 보았
ls ${!source}
으나 현재 디렉터리의 파일이 반환됩니다.시도했지만
ls \$$source
첫 번째 오류로 다시 실패했습니다.
'/home/{x,y}'
스크립트가 실행되도록 스크립트의 매개변수를 확장하려면 어떻게 해야 합니까 ls /home/x /home/y
?
답변1
일반적인 접근 방식은 옵션 플래그 없이 디렉터리를 기본 명령줄 인수로 전달하는 것입니다. 즉, 사용자는 my-script -a -b foo /home/me/dir1 /some/other/path
구문 분석 옵션을 실행한 후 getopts
위치 인수에 디렉토리를 유지하고 실행할 수 있습니다 ls "$@"
. 여기서 사용자는 또는 셸에서 채울 수 있는 확장을 사용하여 마지막 인수를 채울 수 /some/path/{foo,bar}
있습니다 /some/path/*
.
또는 사용자가 -d
실행하는 항목에 여러 옵션을 전달하도록 합니다. 여기서 확장을 사용하는 것은 셸에서 허용하는 모든 항목을 각 인수 앞에 추가 my-script -a -b foo -d /home/me/dir1 -d /some/other/path
해야 하기 때문에 더 어렵습니다 . -d
어쩌면 비슷한 것이 있을 수도 있습니다 a=(/path/{this,that}); my-script -a -b foo "${a[@]/#/-d}"
.
그럼에도 불구하고 스크립트에서 쉘의 확장을 복제하는 것은 흔하지 않으며 사용자를 당황하게 만들 수 있으므로 권장하지 않습니다. 이렇게 한다면 당신도 결정을 내려야 할 것이다어느지원하도록 확장되었습니다. 모든 확장이 모든 셸에서 지원되는 것은 아니며, 각 셸에서 지원되는 모든 확장이 모든 사용자에게 알려진 것은 아닙니다.
답변2
예.sh:
#!/usr/bin/env bash
FILE_PATTERN="$1"
MATCHING_FILES=$(eval "echo $FILE_PATTERN")
echo "Files: $MATCHING_FILES"
ls -l $MATCHING_FILES
이것은 example.sh의 첫 번째 인수를 쉘 글로브 패턴으로 사용합니다. 공백이나 특수 문자가 포함된 파일 이름이 손상될 수 있습니다. 패턴을 적용하는 동안 이를 방지하기 위해 변수를 참조하는 방법은 사용자가 알아내는 것입니다.
용법:
$ ./example.sh 'file-{x,y}.txt'
Files: file-x.txt file-y.txt
-rw-r--r-- 1 user group 0 30 Sep 16:47 file-x.txt
-rw-r--r-- 1 user group 0 30 Sep 16:47 file-y.txt
가능하다면 가급적이면아니요이 작업을 수행하고 여러 파일 이름을 인수로 받아들입니다. 확실히 변수 참조가 더 명확하고 쉬워지며, glob 패턴처럼 보이는 파일 이름에 대한 Stéphane의 문제를 처리하는 것을 피할 수 있습니다.
답변3
나는 그것을 할 것이다:
#! /bin/bash -
sources=()
while getopts d:... o; do
case $o in
(d) sources+=("$OPTARG");;
(...) ;;
esac
done
shift "$((OPTIND - 1))"
ls -- "${sources[@]}"
즉, 호출자가 -d
각 디렉터리에 대해 하나의 디렉터리를 사용하는 디렉터리 목록을 스크립트에서 가져오도록 합니다.
그러면 사용자는 다음 작업을 수행할 수 있습니다.
my-script -d/home/{x,y}
쉘이 중괄호 확장을 지원하는지 또는 쉘이 이 목록을 작성하는 데 도움이 되는 기능을 제공하는지 여부.
rc
// 에서는 fish
다음 zsh -o rcexpandparam
과 같을 수 있습니다:
my-script -d$array
예를 들어 ( in -d$^array
없이도 가능 )rcexpandparam
zsh
존재하다 zsh
:
my-script /home/*(P[-d])
등.
스크립트가 다른 형식의 확장 대신 인수의 중괄호 확장을 수행하도록 하려면 및 ( 스타일 문자를 허용하려는 경우 )을 {
제외한 }
모든 문자 시퀀스를 인용한 다음 실행할 수 있습니다 .,
.0-9
{1..10}
eval
zsh
사용하기가 더 쉬울 수도 있고 의 기능이 매우 제한되어 있기 ksh93
때문입니다 .bash
${var//pattern/replacement}
#! /bin/zsh -
source=${1?}
set -o extendedglob
eval "sources=( ${source//(#m)[^"{}".,0-9]##/'$MATCH'} )"
printf ' - "%s"\n' "$sources[@]"
예:
$ myscript 'x\{1..3}$$`{a b,c}'
- "x\1$$`a b"
- "x\1$$`c"
- "x\2$$`a b"
- "x\2$$`c"
- "x\3$$`a b"
- "x\3$$`c"
그러나 그러면 사용자는 더 이상 리터럴 foo{a,b}
매개변수를 전달할 수 없습니다.
답변4
이는 하나가 아닌 여러 매개변수로 평가되기 때문에 발생합니다. 이 시도:
ls "$@"
$@
모든 매개변수를 공백으로 구분된 문자열로 확장합니다.