I can change the filename for a file to the first word in the file.
for fname in lrccas1
do
cp $fname $(head -1 -q $fname|awk '{print $1}')
done
But I would like to extend it inset.
for fname in lrccas1
do
cp $fname $(head -1 -q $fname|awk '{print $1 FILENAME}')
done
I have tried different variations of this, but none seem to work. Is there an easy solution?
Kind regards Svend
CodePudding user response:
Firstly, let understand why you did not get desired result
head -1 -q $fname|awk '{print $1 FILENAME}'
You are redirecting standard output of head
command to awk
command, that is awk
is reading standard input and therefore FILENAME
is set to empty string. Asking GNU AWK
about FILENAME
when it does consume standard input does not make much sense, as only data does through pipe and there might not such things as input file at all, e.g.
seq 10 | awk '{print $1*10}'
Secondly, let find way to get desired result, you have access to filename and successfully extracted word, therefore you might concat them that is
for fname in lrccas1
do
cp $fname "$(head -1 -q $fname|awk '{print $1}')$fname"
done
Thirdly, I must warn you that your command does copy (cp
) rather than rename file (rm
) and does not care if target name does exist or not - if it do, it will be overwritten.
CodePudding user response:
Here's a different approach with bash
and awk
:
#!/bin/bash
for fname in lrccas1
do
if IFS='' read -rd '' new_fname
then
mv -vi "$fname" "$new_fname"
fi < <(
awk '$1 != "" { printf("%s%s%c", $1, FILENAME, 0); exit }' "$fname"
)
done
What's going on here:
awk
will only print aNUL
byte if it finds a "word" in the input file, so theread
command will return false for blank/empty/non-existing files.The standard input of the
mv
command is the same as theread
, so it'll be empty in reply to a possible prompt about overwriting the destination file, which means "do not do it".
CodePudding user response:
You can do it in pure bash
(or sh
)
for fname in lrccas1
do
read -r word rest < "$fname" && cp "$fname" "$word$fname"
done
CodePudding user response:
This would do what your shell script appears to be trying to do:
awk 'FNR==1{close(out); out=$1 FILENAME} {print > out}' lrccas1
but you might want to consider something like this instead:
awk 'FNR==1{close(out); out=$1 FILENAME "_new"} {print > out}' *.txt
so your newly created files don't overwrite your existing ones and then to also remove the originals would be:
awk 'FNR==1{close(out); out=$1 FILENAME "_new"} {print > out}' *.txt &&
rm -f *.txt
That assumes your original files have some suffix like .txt
or other way of identifying the original files, or you have all of your original files into some directory such as $HOME/old and can put the new files in a new directory such as $HOME/new:
cd "$HOME/old" &&
mkdir -p "$HOME/new" &&
awk -v newDir="$HOME/new" 'FNR==1{close(out); out=newDir "/" $1 FILENAME} {print > out}' * &&
echo rm -f *
remove the echo
when done testing and happy with the result.