異なるフォルダに同じ名前のファイルがたくさんあります。すべてのパスを見つけてテキストファイルに書き込むにはどうすればよいですか?
これは、ファイル名が重複していることはわかっているが、ファイル名がわからないという一般的なケースを処理します。
find -type f -print0 |
awk -F/ 'BEGIN { RS="\0" } { n=$NF } k[n]==1 { print p[n]; } k[n] { print $0 } { p[n]=$0; k[n]++ }'
awk
スクリプト内では、NULLで終了するファイルパスを処理し(改行を含む可能性のあるファイル名を処理できるようにします)、現在のファイルパス名として$0
を使用します。変数n
は、ファイル名コンポーネントを保持します。 k[]
は、このファイル名の出現回数をカウントするハッシュ(n
でキーが付けられたもの)であり、p[]
は(n
でキーが付けられた)別のハッシュです最初に対応する完全パス名を保持します。
例
# Preparation
mkdir -p tmp/a tmp/b
touch tmp/a/xx tmp/a/yy tmp/b/yy tmp/b/zz
# Do it
find tmp -type f -print0 |
awk -F/ 'BEGIN { RS="\0" } { n=$NF } k[n]==1 { print p[n]; } k[n] { print $0 } { p[n]=$0; k[n]++ }'
tmp/a/yy
tmp/b/yy
# Tidyup
rm -rf tmp
find
を使用します。そのようです:
find <path> -type f -name <filename> > same_name.txt
例:
find . -type f -name "foo" > same_name.txt
cat same_name.txt
./dir_a/foo
./foo
./dir_b/foo
./tmp/foo
上記は、現在のディレクトリから始めて、foo
という名前のすべてのファイルを再帰的に検索します。結果はファイルsame_name.txt
に保存されます
インストールされている場合は、locate
を使用できます。
locate filename
またはファイルに保存:
locate filename > same_name.txt
特定の場所のみを検索するには、grepを使用して結果をフィルタリングできます。
locate filename | grep "/path/"
# e.g. search only in your /home folder
locate filename | grep "$HOME"
注:
locate
は、ハードドライブの1日1回のスキャンでデータベース検索を実行するため、find
よりもはるか高速です。cat /etc/updatedb.conf
を実行して、除外されているものを確認してください)。これは、複数回出現するすべてのファイル名を検索する完全なスクリプト(私はfind-double-names.sh
と呼びます)です。クリーンアップする場合は、同じ名前のファイルの内容が異なる可能性があることに注意してください。
例えば。ホームディレクトリ内のすべての二重ファイル名を見つけるには、次のように実行します。
find-double-names.sh $HOME
検索に含めるディレクトリをさらに渡すことができます。例:
find-double-names.sh $HOME /usr/local /var/tmp
多くのファイルがある場合、このスクリプトの実行には時間がかかることがあり、/ tmpにディスク容量が必要になる場合もあります。
#!/bin/bash
# This is the name of this script itself.
#
script="${0##*/}"
# The arguments passed to this script are the parent
# directories to be searched, e.g: /home/me /usr/local
# Check if any given. If not, error out.
#
if [ -z "$1" ] ; then
echo "Usage: $script <directory> [<directory>][...]" >&2
exit 1
fi
# Create a temporary directory. For accurate results we need
# to be sure it is empty. This is one way to do this: create
# an temp dir that is garanteed to not exist yet.
#
# If you want to keep the "outputdir" with the results, make sure
# output dir you use does not contain files you want to keep, because
# files will be removed from it by this script! Better yet, make
# sure it is empty before starting this script.
#
outputdir=$(mktemp --tmpdir -d "${script}.XXXXXXXXXX") # ensures new unique directory
trap "rm -r $outputdir" INT HUP QUIT ABRT ALRM TERM EXIT # ensures it is deleted when script ends
# Search the directories given as arguments, and process
# the paths of alle files one by one in a loop.
#
find "$@" -type f | while read path ; do
filename="${path##*/}"
echo "$path" >>"${outputdir}/${filename}.txt"
done
# Finally, if you want to end up with only file names that
# occur more than once, delete all output files that contain
# only one line.
#
for outputfile in $outputdir/*.txt ; do
linecount=$(wc -l "$outputfile" | sed 's/ .*//') # count lines in it
if [ "$linecount" = "1" ] ; then # if only one line
rm "$outputfile" # remove the file
fi
done
# Print the final result
#
for outputfile in $outputdir/*.txt ; do
cat "$outputfile"
echo # empty line to separate groups of same file names
done
次のbash
スクリプトは、スクリプトへのコマンドラインで指定されたトップレベルパス(またはパスがない場合は現在のディレクトリ)で複製されているすべての通常ファイル(または通常ファイルへのシンボリックリンク)の名前を再帰的に検索します与えられます)。
最後に、重複する各ファイル名の概要が:
で区切られた、ファイル名が見つかる可能性のあるディレクトリ名のリスト。
#!/bin/bash
shopt -s globstar # enable the ** glob
shopt -s dotglob # also let patterns match hidden files
declare -A dirs # where we store directories for each found name
for pathname in "${1:-.}"/**; do
[ ! -f "$pathname" ] && continue # not something we're interested in
name=${pathname##*/}
if [ -n "${dirs[$name]}" ]; then
# we have seen this filename before
dups+=( "$name" )
fi
# append directory name to ':'-delimited list for this filename
dirs[$name]=${dirs[$name]:+"${dirs[$name]}:"}"${pathname%/*}"
done
# go through the list of duplicates and
# print the found directory names for each
for name in "${dups[@]}"; do
printf '%s:\n\t%s\n' "$name" "${dirs[$name]}"
done
実行例:
$ bash script.sh
somefile:
./a:./b
.profile:
.:./t
概要では、.profile
は現在のディレクトリとディレクトリt
にあり、そのsomefile
はディレクトリa
とb
にあります。