多くのフォルダを作成し、その中でいくつかのことをしたいと思います。フォルダ名は、for
ループ内で変数として定義された複数の化学元素の配列に基づいています。
for Element in Cr Hf Mo Nb Ta Ti V W Zr
CrHfMoNb
、、...などの文字を含むCrHfMoTa
サブフォルダを取得できるように、アルファベット順に4つの要素のすべての順列のフォルダが必要です。これを行うために4つのネストされたループを試しましたが、for
単純化のためにここでは2つのループだけを使って説明します。私が思いついたコードは次のとおりです。
for Element in Cr Hf Mo Nb Ta Ti V W Zr; do
for Elemen in Hf Mo Nb Ta Ti V W Zr; do
mkdir "$Element""$Elemen"N # the N at the end is intended
done
done
TiNbN
これにより、目的のフォルダが作成されますが、orZrVN
やlikeなどのアルファベット以外の組み合わせも取得されるため、不要なフォルダもたくさん作成されますHfHfN
。 3行目にifステートメントを追加すると、重複エントリを削除できます。
do [ "$Element" != "$Elemen" ] && mkdir "$Element""$Elemen"N
しかし、これらの重複フォルダは完全に消えませんでしたが、代わりに私のディレクトリの「ゴースト」ファイルになりました。つまり、HfHfN
ファイル拡張子なしでetcとして呼び出されました。しかし、実際の問題は残りのフォルダです。次のようなifステートメントを追加してみました。
do [ "$Element" != "$Elemen" ] && [ "$Element" > "$Elemen" ] && mkdir "$Element""$Elemen"N
許容される順列の数は減りますが、何も削除されません。また、ifステートメントを独自のforループに分割してみましたが、何も変更されませんでした。
for Element in Cr Hf Mo Nb Ta Ti V W Zr; do
[ "$Element" != "$Elemen" ] && [ "$Element" > "$Elemen" ] &&
for Elemen in Hf Mo Nb Ta Ti V W Zr; do...
>
これが正しいコマンドであるかどうかはわかりませんが、if
このリストからhttp://tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.htmlこれが最も意味のあるようです。同様のコマンドを使用すると-ne, -lt, -le, -gt
整数が必要なため、機能しないため、文字は許可されません。結局のところ、4つのループをグループ化してみるのは少し難しくなりました。私は何を見逃していますか?
ベストアンサー1
#/bin/sh
# shellcheck disable=SC2046
# ^ word-splitting by the shell is intentional in this file
elems="Cr Hf Mo Nb Ta Ti V W Zr"
for a in $elems
do
for b in $elems
do
for c in $elems
do
for d in $elems
do
# for a set of any four elements:
# string them together, separated by NUL-bytes
# sort them lexicographically ...
# ... with NUL separating the elements (-z)
# ... and eliminate duplicates (-u)
# then replace the NUL bytes with line breaks
# allow the shell to split on those line breaks
# and chuck the resulting chunks into $1, $2, etc
set -- $(printf '%s\0' "$a" "$b" "$c" "$d" | sort -z -u | tr "\0" "\n")
# only if the current selection of elements consisted of four
# different ones (remember we eliminated duplicates):
if [ $# -eq 4 ]
then
# create a directory, don't error out if it already exists (-p)
mkdir -p "$(printf '%s' "$@")"
fi
done
done
done
done
非常に効率的ではありませんが、(sort
明白な非候補者を呼び出してmkdir
同じディレクトリ名を複数回呼び出す場合でも)、内部ループは最大9 4 = 6561の反復を実行し、ワンタイムスクリプトなのでそうではないと思います。最適化に時間を費やす価値があります。
編集:
Xeon E3-1231v3のベンチマーク、いいえmkdir
:
./elemdirs.sh > /dev/null 11.66s user 1.73s system 173% cpu 7.725 total
そしてそれと一緒に:
./elemdirs.sh > /dev/null 13.80s user 2.16s system 156% cpu 10.215 total
予想数である126個のディレクトリを作成します。コンビネーションここでk = 4、n = 9です。