Enclosing brackets when setting variables - linux

Why does this command destroy the search path?
PATH=($PATH:$HOME/bin)
The PATH appears unchanged, but the shell cannot find commands.
It was entered in error for
PATH=$PATH:$HOME/bin
Probably confused with
PATH=$(echo $PATH:$HOME/bin)

Using parentheses you create an array:
$ a=(x:y:z v:w:x)
$ echo ${a[0]}
x:y:z
$ echo ${a[1]}
v:w:x
In your case you created an array with one element (the whole path). This is then not interpreted anymore as the path to search for executables. This PATH has to be a string of directories separated by colons, not an array.

If you want to acheive PATH=$PATH:$HOME/bin
Try PATH=(\$PATH:\$HOME/bin)

Related

how to use user defined variables in file path concatenation using shell script

$var='system1'
data=C:/data/$var/current_extract/*
Output should be
data=C:/data/system1/current_extract/*"
but i still see the result C:/data/$var/current_extract/* $var value is
**system1** not showing the path
Remove the dollar in the assignment
var='system1'
For setting a variable in Linux variable_name=value. For displaying it you have to prefix the variable name with $ symbol. for example echo $variable_name
var='system1'
data=C:/data/$var/current_extract/*

string manipulation of Directory structure

Scenario: I have a script but no idea where I am in the directory tree, I need to resolve back to the nearest known location UPROC[something]
What I have so far:
I have a script running in a directory for example:
/home/jim/query/UPROCL/test/bob/dircut.sh
now the only constant in this is that the Directory I want will begin with UPROC... maybe not UPROCL but definitely UPROC
So I have written the following:
#!/bin/bash
#Absolute path for this script
SCRIPT=$(readlink -f "$0")
echo $SCRIPT
#Gets Path of script without script name
SCRIPTPATH=$(dirname "$SCRIPT")
echo $SCRIPTPATH
#Cuts everything after UPROC(.* is wildcard)/
CUTDOWN=$(sed 's/\(UPROC.*\/\).*/\1/' <<< $SCRIPTPATH)
echo $CUTDOWN
The only problem is that it output is:
/home/jim/query/UPROCL/test/bob/dircut.sh
/home/jim/query/UPROCL/test/bob
/home/jim/query/UPROCL/test/
Can some tell me what is wrong with my sed command as it is not cutting down to
/home/jim/query/UPROCL/
Because * is greedy. You want to be more selective about what characters are allowed following "UPROC" -- any non-slash
Not
sed 's/\(UPROC.*\/\).*/\1/'
but
sed -r 's,(UPROC[^/]*/).*,\1,'
Using different delimiters for the s/// command reduces the "leaning toothpick" problem.
Because the .* in the () is matching to the / at the end of test/.
You need [^/]* instead of . to not match any slashes.
When you want to know in which directory you are, why don't use pwd?
One thing which might be useful: the command pwd shows the value of the environment variable PWD (uppercase). In case you want to use the current directory as a value, you might use this.

Shell Variables are empty when called in a file name but not when echo'd or called elsewhere

I have 4 shell variables set
remote_account="raccname"
remote_machine="server"
First_Name="firstname"
Last_Name="lastname"
when I call remote_account or remote_machine in my script they get used fine
echo "What directory shall you choose?"
read dir
scp -r ~/csc60/$dir $remote_account#$remote_machine:directoryA
exit;;
but when I call the other two as such
echo "What directory shall you choose?"
read dir
scp $remote_account#$remote_machine:tars/$Last_Name_$First_Name_$dir.tar.z ~/tars
exit;;
it grabs the tars file from tars/$dir.tar.z completely skipping $Last_Name_$First_Name_
when I throw an echo $Last_Name in it still shows it as "lastname"
Is there some rule using "_" between variables or something, or am I just missing something obvious?
_ is a valid character for variable names, therefore you have to qualify which part is the variable.
scp "$remote_account#$remote_machine:tars/${Last_Name}_${First_Name}_$dir.tar.z" ~/tars
You need to delimit your variable value using ${}, as you declared $Last_Name_$First_Name_$dir is treated as one variable and shell put value for it. As in your case you did not defined value for it . It will be intepreted as "".
use ${LAST_NAME}_${FIRST_NAME}

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.

linux batch rename directories and strip # character from name

i have a directory with a lot of subdirectories with a # infront of them:
#adhasdk
#ad18237
I want to rename them all and remove the # caracter
I tried to do:
rename -n `s/#//g` *
but didn't seem to work.
-bash: s/#//g: No such file or directory
Any ideas on this.
Thanks
Just use
$ rename 's/^#//' *
use -n just to check that what you think it would happen really happens.
In you example you have the clue about the wrong quotes used (backticks) in the error message
-bash: s/#//g: No such file or directory
bash is trying to execute a command named s/#//g.
No that using g (global) and not anchoring the regular expression you will replace any #, not just the one in the first position.
I don't know whether it's just a typo when you typed it here, but that "rename" command should work if:
you leave off the "-n" and
you quote the substitution with regular single-quotes and not back-quotes
The "-n" tells it to not really do anything. The back-quotes are just wrong (they mean something but not what you want here).
The problem is that you use backticks (`). You should use normal quotes:
rename -n 's/#//g' *
for DIR in \#*/
do
echo mv "$DIR" "${DIR/#\#/}"
done
I had to rename all folders inside a given folder. Each folder name had some text inside round braces. The following command removed the round braces from all folder names:
rename 's/(.+)//' *
Some distros doesn't support regexp in rename. You have to install prename. Even more, sometimes you can't install prename and you have to install gprename to have binary prename.
If you have 'prename' then just change backtick character " ` " to single quote and everything should work.
So the solution should be:
prename -n 's/#//g' *
or
prename -n 'y/#//' *

Resources