How can I rename all files within a folder with the first word of their content? For example if a.txt contains “Unix is an OS” in its first line then a.txt should be renamed to Unix.txt

  • Please correct title into something like "How do I rename multiple file in unix?"
    – Johan
    May 14, 2011 at 9:55
  • Missed that on this site, I thought I did not have enought rep here...
    – Johan
    May 14, 2011 at 11:11
  • That title is also too misleading. It leaves out the core detail that the new name must be based on file content.
    – jmtd
    May 20, 2011 at 12:41

6 Answers 6


Try this:

for f in *.txt; do d="$(head -1 "$f" | awk '{print $1}').txt"; if [ ! -f "$d" ]; then mv "$f" "$d"; else echo "File '$d' already exists! Skiped '$f'"; fi; done

or more long variant (as script):

for f in *.txt; do
    d="$(head -1 "$f" | awk '{print $1}').txt"
    if [ ! -f "$d" ]; then
        mv "$f" "$d"
        echo "File '$d' already exists! Skiped '$f'"

In case when destination file exists this one-liner skips it.

  • 5
    I'd simplify head -1 "$f" | awk '{print $1}' to <"$f" awk {print $1; exit}. May 14, 2011 at 11:09
  • This doesn't work if the first line has spaces in it...
    – Guillochon
    Nov 8, 2017 at 16:22

Here is my approach.

for file in *; 
    if [[ -f $file ]]; 
        # cut word by single white space
        fileword=$(head -n1 "$file" | cut -f1 -d" ");
        # Everything after first dot is considered as extention
        ext=$(echo $file | sed 's/.*\.\(.*\)/.\1/g')
        [ "$file" != "$fileword" ] && $(mv  "$file"  "$fileword$ext")

Use this oneliner

for i in *; do if [ ! -f $i ]; then echo "skipping $i"; else newname=`head -1 $i | sed 's/^\s*\([a-zA-Z0-9]\+\).*$/\1/'`; [ -n "$newname" ] && mv -i $i $newname.txt || echo "error at: $i"; fi; done

This will replace all files with the first word in that file + .txt. I defined first word to be the first occurrence of [a-zA-Z0-9]+, discarding leading white spaces.
Disclaimer: Please just use it if you are sure that there is a first word on line one in each file! Otherwise you might experience unexpected results ;-)

for i in *.txt
d="$(head -1 "$i" | cut -d " " -f1).txt";
mv "$i" "$d"
  • The character after the first word could be different than space (a comma for example) Nov 19, 2012 at 18:40
for i in *.txt; do mv "$i" "$(head -1 "$i")".txt; done

On your own risk: :)

find -exec echo -n mv {} " " ";" -exec sed '1s/ .*//;q' {} ";" > tmp.sh && bash tmp.sh

This works with easy filenames, containing easy words. A file "O'Reilly" containing as first word "Eto'o" will fail. Miserably.

  • You're missing a step of quoting. What if there's a file called some'thing, or if the first word is D'oh? Jun 14, 2011 at 9:18
  • Yes, I see. How would you do it? Not at all - choose a different approach? Jun 14, 2011 at 20:00
  • It's technically possible to generate a shell script, but it's calling for trouble. You “just” need to get the quoting right. There's no call for it here, just extract the first word and call mv right there, like the other answers. You can keep your sed command, it's a fine way to extract the first word. Jun 15, 2011 at 8:04
  • In praxis, I would, if I used this approach, use two commands - ... > tmp.sh, and review tmp.sh manually. Then invoke bash tmp.sh. With a lot of funky filenames, I wouldn't do it at all. But one or two manual corrections would be fine in 100 files. In about 1000 files, a manual review would start becoming work. Jun 15, 2011 at 17:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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