5

I have the next problem:

Directory Example1 has three files: Example1, Things and Pictures.

Directory Example2 has three files: Example2, Example3 and Pictures.

I need a list showing only the files that match the directory name, this is: Example1 and Example2. I have tried with diff, find, locate and ls... but I have not achieved anything.

  • 4
    Where do you want to find these? In the entire filesystem? In one directory only? – terdon Apr 8 at 11:06
  • Hi!! Only in one directory. Thanks – ChangKo Apr 8 at 18:51
8

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.

| improve this answer | |
  • It doesn't work for me I don't know where the error might be Thanks – ChangKo Apr 9 at 21:21
  • @ChangKo Does it display an error, or does it just not output anything? If I run that exact code, I do find occurrences of files that are located in directories that have the same name as the file. – Kusalananda Apr 9 at 21:23
  • @ChangKo The code will only look at directories below the current directory. Use "$HOME" (or ~) in place of the initial . to look in or below your home directory. – Kusalananda Apr 9 at 21:27
  • It just doesn't do anything. I don't know why. Thanks for your time. I have also tried $ home. – ChangKo Apr 9 at 21:39
  • @ChangKo When you say "files" in the question, you you actually mean file? The name Pictures seems to be the name of a directory. Test my code again, but change -f to -e (so that you have [ -e "$filepath" ]). This will detect any type of name, not just names of files. Also note that if you retype the code, all quotes needs to be exactly as shown in the answer. – Kusalananda Apr 9 at 21:42
19

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'
| improve this answer | |
  • 1
    +1 Didn't know that you could have a backreference in the same find -regex. – pLumo Apr 8 at 11:49
  • 1
    Can you please add an explanation of this regex ? – forzagreen Apr 10 at 10:53
  • @forzagreen Done – Gilles 'SO- stop being evil' Apr 10 at 11:44
5

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
| improve this answer | |
  • find -exec .. \; is slow – mosvy Apr 8 at 23:25
  • How many processes does this fork for a tree of 1000 files? – Jens Apr 9 at 18:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.