Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Alright, so I have a file full of thousands of strings. Each one on it's own line. I want to make a script that will allow me to take this file, call it list.txt, and take the items from each line, and place it into separate files based on the first letter or number. As an example, say the first few lines of the file are like this:


I need to break it down into these:













I would like to accomplish this with BASH, on OS X. Thanks.

Oh, if it helps. Items on each line will NEVER have a space, they will always be contained as one word. E.G. (Never Chicken Soup, instead Chicken-Soup)

share|improve this question
up vote 4 down vote accepted

Try this

typeset -a file
file=($(cat list.txt))
for i in "${file[@]}"; do
    echo $i >> ${i:0:1}.txt

Note, the IFS part is not usually necessary. Also, I tested it on Zsh 4.3.17 on linux and on Bash 4.2.37.

What it does is it declares an array, assigns the contents of the file to that array, then loops over each element of the array, hence each line and echo's that element into the file with the name of the first lettes plus '.txt' appended to it.

share|improve this answer
I just tried using that exact code and just replaced list.txt with my file. However, it took awhile, but after it was done. Nothing happened. Was I suppose to do something else? – Josiah Feb 2 '13 at 18:19
No, it works for me out of the box. Try 'set -x' and then run the command, and pastebin the output, perhaps I can help then. – KoviRobi Feb 2 '13 at 18:23
Looks to be working now. Thanks. – Josiah Feb 2 '13 at 18:24
Yes, 'mkdir' that folder first, then change '${i:0:1}.txt' to 'folder/${i:0:1}.txt' – KoviRobi Feb 2 '13 at 18:26
Whoa... this is much more elegant than the grep/sed-based solution I was going to write up. It's always surprising what bash can do by itself. With that said, you can avoid messing around with $IFS & generally simplify things by using a while loop instead of that for loop. Replace for i in "${file[@]}"; do with while read i; do, and replace done with done <list.txt, and then you can ditch all the stuff outside of the loop. – evilsoup Feb 2 '13 at 18:56

You could just use gawk and simplify things:

gawk '{n=substr($1,0,1); print >> n".txt"}' file.txt
  • n=substr($1,0,1) takes a substring of length 1 starting from the first position (0) of the first field ($1) and saves it into a variable called n.

  • print >> n".txt" will append (>>) each line into a text file called n.txt (where n is the first letter).

To do the same thing for the first two letters, just change the length of substr:

gawk '{n=substr($1,0,2); print >> n".txt"}' file.txt
share|improve this answer
Cool, this is a good answer too. +1! – Josiah Feb 3 '13 at 4:13
Do not forget to close() if your awk stumbled with "too many open files" error, e.g. gawk '{n=substr($1,0,2); print >> n".txt"; close(n".txt")}' file.txt – aff Dec 10 '14 at 8:21

while read line
    if [ -e ${fileName} ];then
    touch ${fileName}
    echo ${line} >> ${fileName}
done < list.txt

The above script takes the first character of each line read in from the list.txt file. It then attempts to create a file with that character + ".txt", and then append each line from list.txt to the appropriate character + ".txt" file.

share|improve this answer
You don't need to explicitly create the file; the >> will create it if it does not exist (unless noclobber has been set, in which case unset it for the script) – alexis Feb 3 '13 at 15:05
Not only do you not need to create it, you are also not creating it at all. -e means check if the file exists and you will only touch the file if that is true. All you are doing is modifying the file's creation date if the file exists. – terdon Feb 3 '13 at 21:31

Your Answer


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.