i've a lot of files (1000+) in a single directory, and i would like to organize them into sub directories, according to their first letter. So i've 200 files starting with A, and i would like to move them into subdirectory "A", then all "B" files etc. etc.

How to do ?

3 Answers 3


In a terminal: cd into the directory in question, then

for x in `ls -1 | sed -e 's/^\(.\).*/\1/' | sort -u`; do
mkdir $x && mv -i ${x}?* $x

This assumes that no files have a single character name before you start. If they do, you might move them aside before you run the above procedure:

mkdir singles && mv ? singles

and then move them to their appropriate destinations aftwards.

Edit: See the comments below for some caveats. If you run into problems with too long command lines, you could replace the second line by

mkdir $x && find . -maxdepth 1 -name "${x}?*" -exec mv -i {} $x \;
  • This fails with files that have spaces (or newlines) in their name. Command substitution might also result in too many arguments.
    – slhck
    Commented May 28, 2012 at 21:50
  • @slhck: No, spaces in filenames are no problem, unless the filename begins with a space. Yes, newlines would be a problem, but both of these cases are distinctly unusual. Command substitution could be a problem if too many filenames start with the same letter. But I think the current limit on command line length is quite generous, so this is not very likely with the number of files indicated. Still, I'll add a fix for that to the answer. Commented May 29, 2012 at 20:12
  • Ah, I see now, my bad, +1 to you!
    – slhck
    Commented May 29, 2012 at 20:13

Here's a Ruby one-liner:

ruby -e 'require "FileUtils"; Dir["*"].each { |f| next if File.directory?(f); d = f[0]; Dir.mkdir d rescue nil; FileUtils.mv(f,d) }'

It basically iterates over all files, creates the directories if possible and moves the files to it afterwards.

Just execute this line from the directory.


This would also work if the filenames start with multibyte characters (like Ä or あ):

ls | iconv -f utf8-mac -t utf-8 | LC_CTYPE=UTF-8 cut -c1 | uniq | while IFS= read -r l; do
  mkdir -- "$l"
  mv -- "${f[@]}" "$l"

iconv -f utf8-mac -t utf-8 converts text from a partially decomposed form used by HFS+ to precomposed form. See Text Encodings in VFS or this question. LC_CTYPE=UTF-8 makes cut -c1 consider multibyte characters as single characters.

You must log in to answer this question.

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