Find files that have the same name as the directory
You can easily match file names that have the same name as the containing directory with a regex using a backreference. These are file names of the form what/ever/something/something
where the two something
parts are identical and don't contain a slash. In BRE regex syntax, [^/]*
matches any string that doesn't contain a slash, \(/[^/]*\)
matches a slash followed by any number of non-slash characters and makes the whole thing a group, and \1
matches the same text that is matched by the first group, therefore \(/[^/]*\)\1
matches two path segments with the same name. Add .*
at the beginning to match the previous directory components.
With GNU find, FreeBSD find, macOS find or any other find
that supports -regex
:
find . -regex '.*\(/[^/]*\)\1'
Since there are generally fewer directories than files, let's look for all directories and then test whether they contain the required filename.
find . -type d -exec sh -c '
for dirpath do
filepath="$dirpath/${dirpath##*/}"
[ -f "$filepath" ] && printf "%s\n" "$filepath"
done' sh {} +
This would print the pathnames of all regular files (and symbolic links to regular files) that is located in a directory that has the same name as the file.
The test is done in a short in-line sh -c
script that will get a number of directory pathnames as arguments. It iterates over each directory pathname and constructs a file pathname with the name that we're looking for. The ${dirpath##*/}
in the code could be replaced by $(basename "$dirpath")
.
For the given example directory structure, this would output
./Example1/Example1
./Example2/Example2
To just test for any name, not just regular files, change the -f
test to a -e
test.
Use find -exec
:
find . -type f \
-exec sh -c '[ "$(basename "$1")" = "$(basename "$(dirname "$1")")" ]' find-sh {} \; \
-print
The -print
will only execute when the result of the [ ... ]
inside the -exec sh -c '...'
is true.
Output:
./Example1/Example1
./Example2/Example2