最近、私のホスティングプロバイダがpublic_html
私が知らない間に私のディレクトリ名を変更したので、この変数宣言はもはや有効ではありません。www
web_application_root="${HOME}/public_html"
public_html"
そのホスティング環境では必ずしも必要ではありませんが、同様の将来の状況のためにBashにXORベースの変数を生成するように指示したいと思いますwww
。
可能であればどのように可能ですか?
答え1
私の考えでは、あなたはもっとうまくできないと思います。
web_application_root="${HOME}/public_html"
if [ ! -d "$web_application_root" ] ; then
web_application_root="${HOME}/www"
fi
さまざまな形で。例えば
for loc in "${HOME}/public_html" "${HOME}/www" ; do
web_application_root=$loc
[ -d "$loc" ] && break
done
本質的に存在する最初のディレクトリを見つけて使用します。
答え2
ここでスレッドの質問に答えようとしています。
*.txt
ワイルドカードは、一致するファイルパスのリストなど、ワイルドカードパターンを拡張したものです。
files=(~/*.txt)
~
名前が配列の個々の要素で終わる隠しファイルのリストを割り当てます(globがファイルと一致しない場合の動作はシェルによって異なります)。.txt
$files
XOR(A, B)
A
or が true の場合は True ですB
が、どちらも True ではないため、次のようになります。AND(OR(A, B), NOT(AND(A, B)))
私はXOR
glob/ワイルドカード演算子を持つシェルを知りませんが、いくつかのシェルには1つのものがOR
ありますNOT
。 )。AND
AND(X, Y)
NOT(OR(NOT(X), NOT(Y)))
XOR
AND-NOT
AND
AND-NOT(X, NOT(Y))
この式を組み合わせると、次のような結果が得られます。
XOR(A, B) == NOT(OR(NOT(OR(A, B)), NOT(NOT(NOT(OR(NOT(A), NOT(B)))))))
これは次のように単純化できます(二重の不正除去)。
XOR(A, B) == NOT(OR(NOT(OR(A, B)), NOT(OR(NOT(A), NOT(B)))))
ksh
またはbash -o extglob
(または)グローバル変数に変換すると、zsh -o kshglob
次のようになります。
!(!(A|B)|!(!(A)|!(B)))
またはzsh -o extendedglob
グローブを使用してください:
^(^(A|B)|^(^A|^B))
または以下を使用してくださいAND-NOT
。
XOR(A, B) == AND-NOT(OR(A, B), NOT(NOT(AND-NOT(A, NOT(B)))))
次のように単純化できます。
XOR(A, B) == AND-NOT(OR(A, B), AND-NOT(A, NOT(B)))
zsh -o extendedglob
globに変換されたら:
(A|B)~(A~^B)
foo*
たとえば、一致するが両方とも一致しないファイルを見つけるには、*.txt
次のようにします。
そしてksh
またはbash -o extglob
(またはzsh -o kshglob
):
files=(!(!(foo*|*.txt)|!(!(foo*)|!(*.txt))))
または以下を使用してzsh -o extendedglob
:
files=(^(^(foo*|*.txt)|^(^foo*|^*.txt)))
または:
files=((foo*|*.txt)~(foo*~^*.txt))
POSIXシェルには、バイナリ(ビット単位)のXOR算術演算子があります。そのまま$(( 1 ^ 2 ))
に拡張されます。3
XOR(0b01, 0b10)
xor
したがって、両方のシェルコードの評価の1つだけがtrueを返す場合は、trueを返す関数を次のように定義できます。
xor() {
eval "$1"; s1=$((!$?))
eval "$2"; s2=$((!$?))
[ "$((s1 ^ s2))" -ne 0 ]
}
match() {
case $1 in
($2) true;;
(*) false;;
esac
}
for file in *; do
if
xor 'match "$file" "foo*"' \
'match "$file" "*.txt"' &&
then
printf '%s\n' "$file"
fi
done