11

I need my script to do something to every file in the current directory excluding any sub-directories.

For example, in the current path, there are 5 files, but 1 of them is a folder (a sub-directory). My script should activate a command given as arguments when running said script. I.e. "bash script wc -w" should give the word count of each file in the current directory, but not any of the folders, so that the output never has any of the "/sub/dir: Is a directory" lines.

My current script:

#!/bin/bash
dir=`pwd`
for file in $dir/*
do
    $* $file
done

I just need to exclude directories for the loop, but I don`t know how.

8
#!/bin/bash -

for file in "$dir"/*
do
  if [ ! -d "$file" ]; then
      "$@" "$file"
  fi
done

Note that it also excludes files that are of type symlink and where the symlink resolves to a file of type directory (which is probably what you want).

Alternative (from comments), check only for files:

for file in "$dir"/*
do
  if [ -f "$file" ]; then
      "$@" "$file"
  fi
done
  • @roaima good idea! – laktak Mar 13 '17 at 19:16
  • 2
    Better to use if [ -f "$file" ]; then .... Not a directory would return not only regular files but sockets and symlinks too. – JRFerguson Mar 13 '17 at 19:29
  • @JRFerguson based on the OP's question I would say that including sockets and pipes would be a really bad idea. As for symlinks, those are implicitly included with ! -d already. – roaima Mar 13 '17 at 20:41
  • I used [ -f $file ] in my final script. Note the lack of quotation marks in the if condition. Almost everywhere I looked had quotation marks around $file, yet I had to delete them in order for my script to work. – Tõnis Piip Mar 14 '17 at 8:07
3

Here's an alternative to using a for loop if what you need to do is simple (and doesn't involve setting variables in the main shell &c).

You can use find with -exec and use -maxdepth 1 to avoid recursing into the subdirectory.

[ -n "$1" ] && find "$dir" -type f -mindepth 1 -maxdepth 1 -exec "$@" "{}" \;

The [ -n "$1" ] is there to avoid executing all the files in the directory when the script isn't passed any arguments.

2

In zsh, you can use glob qualifiers to restrict wildcard matches by file type. For example, adding (.) after the pattern restricts it to regular files.

wc -w *(.)

To cope with file names beginning with - or ., use wc -c -- *(.N) or wc -c ./*(.N). If you want to include symbolic links to regular files as well, make that *(-.).

The other common shells have no such feature, so you need to use some different mechanism for filtering by file such as testing file types in a loop or find.

0

Bash for loop excluding sub-directories ('/') and links (@):

for f in `ls|egrep -v '/|@'`; do echo $f; done

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.