Bash wildcard not expanding

bashmkdirwildcards

I'm trying to make a directory for each file in a directory.

mkdir *

returns File exists. So I try

mkdir *.d

and it makes a directory called "*.d". How do I force the wildcard to expand?

Best Answer

A wildcard always expands to existing names.

Your command mkdir * fails because the names that * expands to already exists.

Your command mkdir *.d "fails" because the *.d does not match any existing names. The pattern is therefore left unexpanded by default1 and a directory called *.d is created. You may remove this with rmdir '*.d'.

To create a directory for each regular file in the current directory, so that the new directories have the same name as the files, but with a .d suffix:

for name in ./*; do
    if [ -f "$name" ]; then
        # this is a regular file (or a symlink to one), create directory
        mkdir "$name.d"
    fi
done

or, for people that like "one-liners",

for n in ./*; do [ -f "$n" ] && mkdir "$n.d"; done

In bash, you could also do

names=( ./* )
mkdir "${names[@]/%/.d}"

but this makes no checks for whether the things that the glob expands to are regular files or something else.

The initial ./ in the commands above are to protect against filenames that contain an initial dash (-) in their filenames. The dash and the characters following it would otherwise be interpreted as options to mkdir.


1 Some shells have a nullglob shell option that causes non-matched shell wildcards to be expanded to an empty string. In bash this is enabled using shopt -s nullglob.

Related Question