Question

I'm having a bit of trouble with globs in Bash. For example:

echo *

This prints out all of the files and folders in the current directory. e.g. (file1 file2 folder1 folder2)

echo */

This prints out all of the folders with a / after the name. e.g. (folder1/ folder2/)

How can I glob for just the files? e.g. (file1 file2)

I know it could be done by parsing ls but also know that it is a bad idea. I tried using extended blobbing but couldn't get that to work either.

Was it helpful?

Solution

WIthout using any external utility you can try for loop with glob support:

for i in *; do [ -f "$i" ] && echo "$i"; done

OTHER TIPS

I don't know if you can solve this with globbing, but you can certainly solve it with find:

find . -type f -maxdepth 1

You can do what you want in bash like this:

shopt -s extglob
echo !(*/)

But note that what this actually does is match "not directory-likes."
It will still match dangling symlinks, symlinks pointing to not-directories, device nodes, fifos, etc.

It won't match symlinks pointing to directories, though.

If you want to iterate over normal files and nothing more, use find -maxdepth 1 -type f.

The safe and robust way to use it goes like this:

find -maxdepth 1 -type f -print0 | while read -d $'\0' file; do
  printf "%s\n" "$file"
done

My go to in this scenario is to use the find command. I just had to use it, to find/replace dozens of instances in a given directory. I'm sure there are many other ways of skinning this cat, but the pure for example above, isn't recursive.

for file in $( find path/to/dir -type f -name '*.js' );
    do sed -ie 's#FIND#REPLACEMENT#g' "$file";
    done

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top