Initialize file name bash shell - Linux

I am trying to initialize a file name in bash but not having much luck. For example, one of my bash scripts outputs a file named "FILE_1000G.vcf". I would like to rename FILE to match with the user's name. This is my code:

set -e
echo "Please enter your filename:"
read filename
rename 's/FILE/$filename/' *

The script prompts the user for their name. Say the user inputs John. The desired output woud be John_1000G.vcf

I keep getting the following error:

Global symbol "$filename" requires explicit package name (did you forget to declare "my $filename"?) at (user-supplied code).

What you have looks like it would try to change a file named FILE_1000G.vcf to instead have the literal name $filename_1000G.vcf assuming that the only file in the directory where you run this script is named FILE_1000G.vcf .

As you know, shell variable expansions are not expanded when $variable_name appears inside single quotes. And, if your system has a rename utility, it probably won't be happy with operands that do not contain the string you're trying to replace. (I know of several systems that have a rename () function in C; but I don't have access to any that have a rename utility.) So, in case your system does have a rename utility that does what I'm guessing you're trying to do, you might want to try:

set -e
echo 'Please enter your name:'
read username
rename "s/FILE/$username/" *FILE*

Assuming that you're using a POSIX conforming shell (which you have not specified), and using just standard utilities, you might want to try something more like:

echo "Please enter your name:"
read username
for filename in *FILE*
do	if [ -f "$filename" ]
	then	prefix=${filename%%FILE*}
		suffix=${filename#*FILE}
		mv "$filename" "$prefix$username$suffix"
	fi
done

This should work in any directory containing zero or more regular files with filenames that contain the literal string FILE one or more times (replacing only the first occurrence of FILE if FILE appears more than once in a filename).

1 Like

Just a small detail:

read username?'Please enter your name:'

Will display the prompt and take the input just as well.

bakunin

Thanks Don, I liked your 1st code, just learned something!

Hi bakunin,
It will with a recent ksh (such as version 93u+). It might with a recent bash , but not with bash version 3.26 (the version included with the latest macOS release) where the following command:

read x?'Prompt: '

prints no prompt, blocks waiting to read a response, and after a response has been entered gives the diagnostic:

bash: read: `x?Prompt: ': not a valid identifier

Other shells might do what you want, might print a diagnostic without waiting for input, or might behave in a manner similar to that shown above.

I tend to use an echo or printf to print the prompt before the read , so I get the desired results with any version of any shell that is based on Bourne shell syntax (since the mid 1970's when using echo or since the late 1980's when using printf ). But, if you know you only want to run your script on a system where the shell you're using has a built-in read utility with prompting, by all means take advantage of the shortcut.

2 Likes

hmm, interesting. I didn't know that. My main shell (ksh88, AIX) does it and i always thought that bash does it too - it seems i was just lucky the few times i used bash .

bakunin

1 Like

You're right. According to the book "THE New Kornshell Command and Programming Language" published in 1995, read issuing prompts was supported in at least some versions of ksh88 as well as in all versions of ksh93 .

This is one of many features that bash adopted from ksh . I don't know which version of bash first included it.