二重置換を使用したBash ls

二重置換を使用したBash ls

私はコマンドライン引数からディレクトリを読み込んで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各ディレクトリに1つのディレクトリを使用するディレクトリのリストをスクリプトから取得するようにします。

これにより、ユーザーは次の操作を実行できます。

my-script -d/home/{x,y}

シェルが中括弧拡張をサポートするのか、シェルがこのリストを作成するのに役立つ機能を提供するのか。

rc// では、fishzsh -o rcexpandparamのようになります。

my-script -d$array

例えば(inなし-d$^arrayでも可能)rcexpandparamzsh

存在する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

これは、1つではなく複数のパラメータで評価されるために発生します。この試み:

ls "$@"

$@すべてのパラメータをスペースで区切られた文字列に展開します。

関連情報