One can achieve this by, for example, using a for
loop, which has the syntax:
for var in values; do things; done
This code puts the first of the list of values
into var
and performs things
on it, then puts the next value into var
and so on.
We often use this to do the same thing to a bunch of files, as you want to do here.
You can use some suitable expression to get Bash to create a list of your files (the list of values, as I've called it above). Here I suggest you use *File.txt
. This would be expanded by the shell to a list of all the files in the current directory that end with File.txt
. So the first bit of your code could be
for f in *File.txt; do
Instead of f
you can use some other name for your variable, such as file
. I suggest using a letter or word in lowercase (there are other variables already defined in the shell with uppercase words, and we don't want to over-ride them). When we call our variable in Bash, we precede its name with $
. So you would refer to your variable with $f
or $file
, and the shell will expand this to the current value of that variable. To prevent further expansions on the result, we almost always use double quotes, so instead of writing $f
, I would write "$f"
when I call my variable.
To send some text into a file you can use simple tools like printf
or echo
with redirection. You have shown that you know how to use redirection to append content to a file. This: stuff > file
replaces the contents of file
with stuff
and stuff >> file
appends stuff
to file
.
We should be really careful with redirection as we can easily overwrite our important files - you won't even get a warning about it. So before you run such a powerful command, you might want to make a backup of your files in another directory, and/or do a dry run where you just check what files are going to be operated on, like this:
for f in *File.txt; do echo "$f"; done
The above simply returns the list of files that will be acted on.
So let's go back to how you are going to add text to the file. Since we already have the name of the file in our variable, we can use that to generate the text.
Here is how your code could look with echo
:
for f in *File.txt; do echo "$f" >> "$f"; done
For firstFile.txt
, that would run echo firstFile.txt >> firstFile.txt
, and so on for all the other files matched by *File.txt
.
But you mentioned that your files end with .txt
and you don't want that to be in the appended text.
To avoid that you can perform some string manipulation
for f in *File.txt; do echo "${f%.*}" >> "$f"; done
This ${f%.*}
trims characters from the last .
character onwards from the string in $f
, in this case the .txt
.
You could also use printf
. It's worth learning as it's more flexible than echo
and, so I'm told, can be more reliable.
for f in *File.txt; do printf '%s\n' "${f%.*}" >> "$f"; done
'%s\n'
is for formatting - %s
means the text is a string (not a number, for example) and \n
appends a newline after it (echo
automatically appends a newline).
echo * >> *.txt
- bash doesn't implicitly loop over multiple things for you. One>>
redirect in one command will only ever open a single file for appending. And theecho
command will only run once, with all those args.