Take the 2-minute tour ×
Ask Different is a question and answer site for power users of Apple hardware and software. It's 100% free, no registration required.

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 ?

share|improve this question
add comment

3 Answers

up vote 3 down vote accepted

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 \;
share|improve this answer
    
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
add comment

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.

share|improve this answer
add comment

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.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.