ファイル名を含む照会ファイルがあります。また、ファイルを含むディレクトリがあり、その中にはディレクトリの特定の名前に対応する名前があります。
私がすることができます:
- 正確に一致するファイルを新しいディレクトリに移動するか、
- 既存のディレクトリから一致しないファイルを削除します。
また、最上位ディレクトリとそのサブディレクトリを介してこの操作を繰り返し実行するにはどうすればよいですか?
答え1
たぶん、次のようなものがあります。
sed -e 's;^.*$;\^&\$; list-of-names > list-of-patterns
rm $(find . -type f | grep -v -f list-of-patterns)
ファイル名にシェルが特別であると見なされるスペースや文字が含まれていると、確実に壊れる可能性があります。実際に実行する前に、何が削除されていることを確認してください!
(スキーマファイルをバイパスする方法があるかもしれませんが、まったく見えません。)
答え2
次のbashスクリプト(警告:テストされていません!)はファイルを下から/directory/with/the/files
下に移動します/matched/files
。/path/to/lookup.file
名前だけでファイルを移動します(ディレクトリを除く)。にディレクトリへのシンボリックリンクがある場合は、/directory/with/the/files
ディレクトリ自体のように再帰的に移動されます。
#!/bin/bash
shopt -s globstar
set -f; IFS=$'\n'
typeset -A filenames
for x in $(cat /path/to/lookup.file); do filenames[$x]=1; done
set +f; unset IFS
cd /directory/with/the/files
for x in ./**; do
if [[ -d "$x/." ]]; then
: # skip directories and symbolic links to directories
elif [[ -n ${filenames[${x##*/}]} ]]; then
# the file is matched, move it under /matched/files
mkdir -p "/matched/files/${x%/*}"
mv "$x" "/matched/files/$x"
else
# the file isn't matched
:
fi
done
説明する:
shopt -s globstar
作る**
全体的な状況ディレクトリを再帰的に移動します。set -f; IFS=$'\n'
ワイルドカードをオフにして、新しい行を唯一の単語区切り文字に設定して、引用符で囲まれていない$(cat /path/to/lookup/files)
コマンド置換を新しい行でのみ分割するようにします。filenames
は連想配列。for x in ./**
$x
ディレクトリ部分は常に含まれます(このように、ディレクトリ${x%/*}
部分は最上位ディレクトリを意味します)で始まりません(したがってオプションとして扱われる危険はありません)。$x
.
-
${x##*/}
ファイル名部分$x
、つまり$x
ディレクトリ部分なしで拡張されます。