(フォルダ)名前リストを処理するためのBashスクリプト

(フォルダ)名前リストを処理するためのBashスクリプト

フォルダ名のリストを含むテキストファイルを繰り返し、そのフォルダの特定のパス(この場合は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}

関連情報