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?"– JohanMay 14, 2011 at 9:55
-
Missed that on this site, I thought I did not have enought rep here...– JohanMay 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.– jmtdMay 20, 2011 at 12:41
6 Answers
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):
#!/bin/sh
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
In case when destination file exists this one-liner skips it.
-
5I'd simplify
head -1 "$f" | awk '{print $1}'
to<"$f" awk {print $1; exit}
. May 14, 2011 at 11:09 -
Here is my approach.
#!/bin/bash
for file in *;
do
if [[ -f $file ]];
then
# 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")
fi;
done
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 ;-)
-
4Gah! Don't parse the output of ls! The shell already knows how to act on all the files in a directory, it's spelled
*
. May 14, 2011 at 11:07
for i in *.txt
do
d="$(head -1 "$i" | cut -d " " -f1).txt";
mv "$i" "$d"
done
-
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
-
2
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 isD'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 invokebash 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