Home > OS >  Extend filename with word from file -
Extend filename with word from file -

Time:10-06

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 a NUL byte if it finds a "word" in the input file, so the read command will return false for blank/empty/non-existing files.

  • The standard input of the mv command is the same as the read, 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.

  • Related