I have several directories which contain hidden empty files. I need the name of these file names themselves, so I need to write the filenames to a txt file. My script looks like this:

cd /z/all_vendors/
x=`find vendors -perm 755`
for FILE  in $x; do
    ls -a $FILE >> locator.txt

However I get a permission denied error How do I write these hidden file names to a directory?

EDITS the vendors directory has subdirectories in the following way


so x=`find vendors -perm 755` finds all subdirectories with certain permissions

Each of the 000xxx subdirectories have the following tree structure:


etc where the hidden files start with a dot

I need to write the names of the hidden files to a txt file for example 'kpypjn32rz6l'

  • (1) Bash pitfall number 1. (2) Quote. (3) "Hidden" meaning "with names starting with a dot"? I'm asking because your code does not try to isolate such files (maybe because there are no non-hidden files?). (4) What does "the name of these file names themselves" mean? "Name of names"… what? Nov 5, 2021 at 22:51
  • hidden meaning they start with a dot, the name of the files represent location codes
    – Fnechz
    Nov 5, 2021 at 22:53
  • 1
    cd /z/all_vendors/ && find vendors -name '.*' >> locator.txt? This is not an answer because although I think the command kinda matches the (not entirely clear) description, I'm not sure if this is what you want, because your code may run ls -a for directories and non-directories. Is -perm 755 your way to find directories maybe? Sorry, there is so much weirdness in the code, I am confused about your desired output. Maybe if you posted an example directory tree (from the command tree, edit the question) and the desired output, we could fix your code so it generates the output you want. Nov 5, 2021 at 23:03
  • Also: what does "copy these hidden file names to a directory" mean? One can copy files (not names) to a directory. Your code writes some names to a file that is (hopefully) not a directory. IMO "copy names to directory" makes no sense. Nov 5, 2021 at 23:04
  • I have edited the question
    – Fnechz
    Nov 5, 2021 at 23:23

1 Answer 1

cd /z/all_vendors/ \
&& find vendors \
   \( -type d ! -path vendors ! -perm 755 -prune \) -o \
   \( -type f -name '.*' -exec basename -a -- {} + \) \
| sed 's/^\.//' >> locator.txt


  • If cd fails then find will not be executed. This is good practice.
  • Any directory that doesn't match -perm 755 will be pruned (i.e. find will not descend into it), regardless of its depth. It could be wrong e.g. if you wanted to descend many levels regardless of permissions and only check permissions of the bottom-level directory. I understand your directory structure is quite flat, so this shouldn't be a problem. With ! -path vendors I ensure vendors will not be pruned, regardless of its permissions. (Note this is very sensitive to the path you supply to find as the starting point. find vendors/ … requires ! -path vendors/; find ./vendors … requires ! -path ./vendors etc.)
  • I assumed by "file" you mean "regular file", therefore -type f. Formally "file" is a broad term.
  • basename is a portable tool but its -a option is not portable. If your basename does not support -a then replace -exec basename -a -- {} + with -exec basename -- {} \;.
  • Hopefully the filenames to be printed don't contain any newline characters. Newlines will terminate names. The standard approach in case filenames may contain newlines is terminating with null characters. Terminating with null characters would complicate our solution and make locator.txt not a text file (POSIX definition of text file explicitly states it does not contain null characters).
  • sed removes one leading dot per line.
  • Files with identical names from different directories, if they match, will result in identical lines of output. Pipe to sort -u if you want to remove duplicate lines.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .