Replace extension using basename in one line of code - linux

In bash linux
v1=$(basename $0) gives filename.ext
v1=${v1%.*}.log replaces ext filename.log
how to combine in one line? When I try below I get bad substitution error
v1={($(basename $0))%.*}.log
thank you

You can only use parameter expansion on parameters, so in general you can't do this.
However, in this specific case you can reorder the operations since it doesn't matter whether you basename or strip extension first:
v1=$(basename "${0%.*}.log")

Related

How to remove a substring from string in SH not bash

I would like to modify input parameters of an SH script (it begins with #!/bin/sh). I found some solutions but they don't work here and need bash. They give me bad substitution error. so I look for a solution that works in SH (or whatever it is called)
The bash_params could be like "_learn _vil=bar _meet=foo". Here "_learn" acts as a flag. I want to set some variabels based on this flag and then remove it so that I can set other variables with eval.
Also, if you know better approaches please let me know
case $bash_params in
*"_learn"*) # learn is enabled
_learn_sp=True
tt="_learn"
bash_params="${bash_params%"$tt"}" # it doesn't work
bash_params="${bash_params/_learn//}" # this gives Bad substitution error
_lsp=False
;;
eval ${bash_params}
Pipe to sed.
bash_params=$(echo "$bash_params" | sed "s/$tt//")

How to read a variable from file, modify and safe it to an other variale

What I want:
There is a file /scripts/backup/config.cfg which contains variables. In my specific case the important ones are:
BACKUPLOCATION=""
ROOTLOCATION="/backup"
Then there is a script /scripts/backup/performBackup.sh
For a specific reason I want a part of the script do the following operations:
read the value of the variable ROOTLOCATION
add a ("/" and) timestamp (Date&Time)
safe the new created value to BACKUPLOCATION (by replacing its current value)
Example
If this is the previous state of the config.cfg:
BACKUPLOCATION="dummy"
ROOTLOCATION="/backup"
After the script ran it should be:
BACKUPLOCATION="/backup/2020-05-02-23-00"
ROOTLOCATION="/backup/"
What I tried
First of all the config file gets "loaded" using
source /scripts/backup/config.cfg
I then tried to use the sed command but the quotes are messing with me. Here is one try (which didn't work):
sed -i 's/BACKUPLOCATION\=.*/BACKUPLOCATION="'$ROOTLOCATION/$(date +%Y-%m-%d-%H-%M)'"/' /scripts/backup/config.cfg
Try this:
source /scripts/backup/config.cfg
sed -i 's|BACKUPLOCATION=.*|BACKUPLOCATION="'"$ROOTLOCATION/$(date +%Y-%m-%d-%H-%M)"'"|' /scripts/backup/config.cfg
The problem with your sed is that you use / as delimiter, which is present in $ROOTLOCATION after expansion, therefore sed fails. I used |, which is usually is not present in filenames. If you ever create a file with |, that sed will fail too! So, "know your data" :)

Using wildcards to exclude files with a certain suffix

I am experimenting with wildcards in bash and tried to list all the files that start with "xyz" but does not end with ".TXT" but getting incorrect results.
Here is the command that I tried:
$ ls -l xyz*[!\.TXT]
It is not listing the files with names "xyz" and "xyzTXT" that I have in my directory. However, it lists "xyz1", "xyz123".
It seems like adding [!\.TXT] after "xyz*" made the shell look for something that start with "xyz" and has at least one character after it.
Any ideas why it is happening and how to correct this command? I know it can be achieved using other commands but I am especially interested in knowing why it is failing and if it can done just using wildcards.
These commands will do what you want
shopt -s extglob
ls -l xyz!(*.TXT)
shopt -u extglob
The reason why your command doesn't work is beacause xyz*[!\.TXT] which is equivalent to xyz*[!\.TX] means xyz followed by any sequence of character (*) and finally a character in set {!,\,.,T,X} so matches 'xyzwhateveryouwant!' 'xyzwhateveryouwant\' 'xyzwhateveryouwant.' 'xyzwhateveryouwantT' 'xyzwhateveryouwantX'
EDIT: where whateveryouwant does not contain any of !\.TX
I don't think this is doable with only wildcards.
Your command isn't working because it means:
Match everything that has xyz followed by whatever you want and it must not end with sequent character: \, .,T and X. The second T doesn't count as far as what you have inside [] is read as a family of character and not as a string as you thought.
You don't either need to 'escape' . as long as it has no special meaning inside a wildcard.
At least, this is my knowledge of wildcards.

Unable to copy a file with '$' in name in Linux

Inside of my Linux directory, I have a file named TopSample$Config.class.
Whenever I try to copy this file to another location/directory, it is not allowing me to do so.
I am doing it this way:
cp TopSample$Config.class /home/praveen/com/config/
Please let me know if this isn't possible.
The shell will interpret $Config as a variable. And it will expand to empty string.
You can put single quotes around to keep the literal value:
cp 'TopSample$Config.class' /home/praveen/com/config/
Another way is to escape the $(dollar sign) by using \(backslash)
cp TopSample\$Config.class /home/praveen/com/config/
Put single quotes around the filename.
cp 'TopSample$Config.class' /home/praveen/com/config
Or replace the offending character with the filename metacharacter of '?', meaning "any one character". Note that while this might be more convenient and requires the fewest keystrokes, be aware that a filename of TopSample?Config.class will also match TopSampleaConfig.class, TopSamplebConfig.class, TopSamplecConfig.class, etc.

Linux rename function not being used correctly

I'm trying to use the rename command in a Terminal in Ubuntu to append a string to the beginning of some avi file names as follows.
rename -n 's/(\w)\.avi$/String_to_add__$1\.avi/' *.avi
So I expect the following:
String_to_add_MyMovie.avi
Problem is that when I run the command it appends the string to the end of the file name, so I end up with the following:
MyMovie_String_to_add_.avi
I'm not sure if I have the perlexpr syntax wrong or something else. Any insight is appreciated.
UPDATE:
Thanks for the suggestions, I tried the suggestions from alno and plundra and made the following modification:
rename -n 's/(\w+)\.avi$/String_to_add__$1\.avi/' *.avi
But now the file gets the string inserted in the middle of the name as follows:
My_String_to_add_Movie
My apologies though, I neglected to mention that the titles are preceded by 3 numeric values, so the file name nomenclature is {3 numbers}-My_Movie.avi so for example 001-My_Movie.avi. But I didn't think this would make a difference since I'm assuming \w+ matches alphanumeric characters, might the '-' be the issue?
Haven't tried Christian's approach yet, I want to be able to use the rename command, or at least understand why it's not working before I try a different approach.
I don't think rename -n is standard. You could do this:
for i in *.avi; do mv $i String_to_add_$i; done
You're only matching a single character with \w, you want \w+, so the complete line would be:
rename -n 's/(\w+)\.avi$/String_to_add__$1\.avi/' *.avi
Correct version:
rename -n 's/(\w+)\.avi$/String_to_add__$1\.avi/' *.avi
You simply forgot + after \w, so it tried to match only one character.

Resources