I've written a script to go through all the files in the directory the script is located in, identify if a file name contains a certain string and then modify the filename. When I run this script, the files that are supposed to be modified are disappearing. It appears my usage of the mv command is incorrect and the files are likely going to an unknown directory.
#!/bin/bash
string_contains="dummy_axial_y_position"
string_dontwant="dummy_axial_y_position_time"
file_extension=".csv"
for FILE in *
do
if [[ "$FILE" == *"$string_contains"* ]];then
if [[ "$FILE" != *"$string_dontwant"* ]];then
filename= echo $FILE | head -c 15
combined_name="$filename$file_extension"
echo $combined_name
mv $FILE $combined_name
echo $FILE
fi
fi
done
I've done my best to go through the possible errors I've made in the MV command but I haven't had any success so far.
CodePudding user response:
The issue is with the filename assignment line:
filename= echo $FILE | head -c 15
This should be written as:
filename=$(echo "$FILE" | head -c 15)
The incorrect line is assigning the output of echo to the variable filename, instead of the result of the head command.
Additionally, you might want to add the -v option to the mv command to have it verbosely show what it is doing:
mv -v $FILE $combined_name
CodePudding user response:
There are a couple of problems and several places where your script can be improved.
filename= echo $FILE | head -c 15
This pipeline runs echo $FILE
adding the variable filename
having the null string as value in its environment. This value of the variable is visible only to the echo
command, the variable is not set in the current shell. echo
does not care about it anyway.
You probably want to capture the output of echo $FILE | head -c 15
into the variable filename
but this is not the way to do it.
You need to use command substitution for this purpose:
filename=$(echo $FILE | head -c 15)
head -c
outputs only the first 15 characters of the input file (they can be on multiple lines but this does not happen here). head
is not the most appropriate way for this. Use cut -c-15
instead.
But for what you need (extract the first 15 characters of the value stored in the variable $FILE
), there is a much simpler way; use a form of parameter expansion called "substring expansion":
filename=${FILE:0:15}
mv $FILE $combined_name
Before running mv
, the variables $FILE
and $combined_name
are expanded (it is called "parameter expansion"). This means that the variable are replaced by their values.
For example, if the value of FILE
is abc def
and the value of combined_name
is mnp opq
, the line above becomes:
mv abc def mnp opq
The mv
command receives 4 arguments and it attempts to move the files denoted by the first three arguments into the directory denoted by the fourth argument (and it probably fails).
In order to keep the values of the variables as single words (if they contain spaces), always enclose them in double quotes. The correct command is:
mv "$FILE" "$combined_name"
This way, in the example above, the command becomes:
mv "abc def" "mnp opq"
... and mv
is invoked with two arguments: abc def
and mnp opq
.
combined_name="$filename$file_extension"
There isn't any problem in this line. The quotes are simply not needed.
The variables filename
and file_extension
are expanded (replaced by their values) but on assignments word splitting is not applied. The value resulted after the replacement is the value assigned to variable combined_name
, even if it contains spaces or other word separator characters (spaces, tabs, newlines).
The quotes are also not needed here because the values do not contain spaces or other characters that are special in the command line. They must be quoted if they contain such characters.
string_contains="dummy_axial_y_position"
string_dontwant="dummy_axial_y_position_time"
file_extension=".csv"
It is not not incorrect to quote the values though.
for FILE in *
do
if [[ "$FILE" == *"$string_contains"* ]];then
if [[ "$FILE" != *"$string_dontwant"* ]]; then
This is also not wrong but it is inefficient.
You can use the expression from the if
condition directly in the for
statement (and get rid of the if
statement):
for FILE in *"$string_contains"*; do
if [[ "$FILE" != *"$string_dontwant"* ]]; then
...
If you have read and understood the above (and some of the linked documentation) you will be able to figure out yourself where were your files moved :-)