評価なしで変数にコマンドを保存する - Unix

評価なしで変数にコマンドを保存する - Unix

後でリモートサーバーで実行できるように、コマンドを変数に保存しようとしています。アスタリスクはフォルダ名に置き換えられ、変数に保存されます。後で使用するためにアスタリスクと同じコマンドが必要です。

スクリプト:

#!/bin/bash
cmd="ls -lrt /client/*/ver* /client/*/*/ver*  | grep 299 | tail -1"
echo $cmd

出力:

./script.sh 
ls -lrt /client/folder299/version_1 /client/ifolder299/ifolder/version_a /client/ifolder300/ifolder1/version_b /client/ifolder301/ifolder2/version_c /client/ifolder302/ifolder3/version_d | grep 299 | tail -1

周りを見回したが運がなかった。誰かがコマンドをそのまま保存する方法を見つけるのに役立ちますか?

ベストアンサー1

コマンドは評価されず、文字列はそのまま変数に格納されます。引用符のない変数を出力すると、ワイルドカードパターンが拡張されます。


cmd="ls -lrt /client/*/ver* /client/*/*/ver*  | grep 299 | tail -1"

これは安全で、cmdリテラル文字列として設定できますls -lrt /client/*/ver* /client/*/*/ver* | grep 299 | tail -1。この場合、文字列の周囲に二重引用符と一重引用符を使用することの違いは重要ではありません(ただし、静的文字列なので一重引用符を使用します)。シェルが文字列で拡張を実行する必要がないという点では重要ではありません。文字列に変数またはコマンド置換がある場合、シェルはそれを拡張しますが、実際には何もしません。

出力変数値を使用すると、echo $cmdワイルドカードパターンが拡張されますが(これが発生します)、コマンドはまだ実行されません。

ワイルドカードパターンの拡張を防ぐには、変数を二重引用符で囲んで展開します"$cmd"。個人的に

printf '%s\n' "$cmd"

その値を印刷します。望むより」なぜprintfがechoより優れているのですか?「なぜ。

関連:


また、解析中なのでls -l(自安全ではない)次に番号を見つけます。どこかに出力にはls -lファイルサイズなどがあります。

解決しようとする大きな問題が何であるかをもう一度考えて、まったく新しい質問をしてみることを提案します。それ代わりに。

パス名リストで最近変更された一般ファイルを見つけるには、次のようにします。

unset newest
for pathname in /client/*/ver* /client/*/*/ver*; do
    if [ -f "$pathname" ] && [ "$pathname" -nt "$newest" ]; then
        newest=$pathname
    fi
done

これは、前述のファイル名globbingパターンが解決したい名前に拡張されていると仮定します。また、文字列を含むファイル名のみを許可するように制限します299

unset newest
for pathname in /client/*/ver* /client/*/*/ver*; do
    if [[ "${pathname##*/}" == *299* ]] &&
        [ -f "$pathname" ] && [ "$pathname" -nt "$newest" ]; then
        newest=$pathname
    fi
done

ワイルドカードパターンが再帰的に見なければならないディレクトリに拡張される場合は、次のようにしますbash

shopt -s globstar
unset newest
for pathname in /client/*/ver*/** /client/*/*/ver*/**; do
    if [[ "${pathname##*/}" == *299* ]] &&
        [ -f "$pathname" ] && [ "$pathname" -nt "$newest" ]; then
        newest=$pathname
    fi
done

SSHを介してこの例を実行します。

ssh user@host bash -s -O globstar <<'END_SCRIPT'
for pathname in /client/*/ver*/** /client/*/*/ver*/**; do
    if [[ "${pathname##*/}" == *299* ]] &&
        [ -f "$pathname" ] && [ "$pathname" -nt "$newest" ]; then
        newest=$pathname
    fi
done
printf 'Newest file: %s\n' "$newest"
END_SCRIPT

おすすめ記事