フォルダ名のリストを含むテキストファイルを繰り返し、そのフォルダの特定のパス(この場合は2021
。
私のlist.txtファイルには、次のリストが含まれています。
100001
100002
100003
100004
...
2021
名前を確認したいサブフォルダを含むディレクトリ(いわゆる)があります。
100001
100002
100004
...
この例では、スクリプトはフォルダが100003
見つからないことを示しているはずです。このスクリプトの目的は、単にテキストファイルにリストされているフォルダがパスから欠落しているかどうかを見つけることです。
これまで私は以下を持っています:
while IFS= read -r line; do
if [[ ! -d "2021/$line" ]]; then
echo $line is missing
fi
done <<< $(cat list.txt)
しかし、このコードはディレクトリ内のすべてのフォルダを印刷するだけなので、2021
文に問題があると推測されますが、IF
わかりません。
答え1
フォルダを含むパスの外でシェルスクリプトを実行しているとします2021
。
次の構造で:
$> tree
#output:
.
├── 2021
│ ├── 100000
│ ├── 100001
│ ├── 100002
│ ├── 100003
│ ├── 100006
│ ├── 100007
│ ├── 100008
│ ├── 100009
│ ├── 100010
│ ├── 100011
│ ├── 100019
│ ├── 100020
├── list.txt
└── script
何も変更せずに現在のスクリプトを実行できるはずです。以下を使用してください。./script
問題は、script
スクリプトディレクトリの外でコードを実行すると、コードが正常に実行されないことです。したがって、スクリプトを次のように変更することをお勧めします。
#!/bin/bash
filepath="$(dirname $(readlink -f $0) )"
cd $filepath
while read -r line; do
if [[ ! -d "2021/$line" ]]; then
echo $line is missing
fi
done <<< $(cat list.txt)
#Or:
# done < /paht/to/list.txt
私はそれを削除しましたIFS=
。なぜ持っているのかわかりませんが、必ず使用する必要がある場合は追加してください。
したがって、任意のディレクトリでスクリプトを実行できます。./path/to/dir/script
次のコマンドを使用して、欠落しているディレクトリをインポートすることもできます。
#With this code you will get only the missing dirs. The text 'is missing'
#won't appear here
diff --new-line-format="" --unchanged-line-format="" <(sort /path/to/list.txt) <(find . -maxdepth 1 -type d ! -path . -printf '%P\n' | sort)
ファイルが実際にソートされている場合は、単純にlist.txt
変更できます。<(sort /path/to/list.txt)
/path/to/list.txt
2021
上記のコードを使用している場合は、ディレクトリの下に配置して/path/to/list.txt
実際のパスに変更します。list.txt
答え2
数時間問題を検索した後、ついに解決策を見つけました。
問題は、ファイルが元のWindows OSで作成されてからbashシェルで使用されることです。つまり、Windowsでは改行とキャリッジリターンで終わりますが、Unixでは単一の改行で終わります。
IF
したがって、ファイルの名前をフォルダの名前と比較すると、リストファイルの名前に誰にも表示されない追加のキャリッジリターンがあるため、明らかに一致することは不可能であると推測されます。
だから私はUnixでファイルを再作成し、期待した結果を完璧に得ました。助けてくれた皆さんに感謝します。
答え3
私はbashの代わりにzshを使います。オプションとして、優れたglobと配列連結(${A:*B}
)と減算(${A:|B}
)演算子を使用できます。
#! /bin/zsh -
list=path/to/list.txt
dir=path/to/2021
# or list=${1?} dir=${2?}
# for instance to pass those as arguments to the script
expected=( ${(f)"$(<$list)"} )
# or expected=( ${(f)"$(dos2unix < $list)"} )
# if that file is in MS DOS/Windows format
got=( $dir/*(ND/:t) )
# or got=( $dir/*(ND-/:t) )
# to also consider symlinks to directories like your [[ -d ... ]] does
report() {
if (( $# > 1 )); then
print -rC1 -- $1: ' - '$^@[2,-1]
else
print -r -- $1: none
fi
}
report Found ${expected:*got}
report Missing ${expected:|got}
report Unexpected ${got:|expected}