2

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 ?

5

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
done

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 \;
3
  • This fails with files that have spaces (or newlines) in their name. Command substitution might also result in too many arguments. – slhck May 28 '12 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. – Harald Hanche-Olsen May 29 '12 at 20:12
  • Ah, I see now, my bad, +1 to you! – slhck May 29 '12 at 20:13
3

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.

0

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
  f=("$l"*)
  mkdir -- "$l"
  mv -- "${f[@]}" "$l"
done

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 .