shell variables advanced

Hi all, i have more questions but its all about variables so lets begin

1st, is possible to list all variables ?
Command env display only shell variables, but what if i declared another variable? Command set display more variables but not defined by me.

2nd, what difference is between set and env ?

3rd, lets say i declared variable which contains whitespaces, or i have variable which contains whitespaces for example IFS. When i type echo $IFS i see nothing, so i dont know if is declared or if contain white spaces.
Is possible to write white spaces in C format (\n \r \t ...) ?

4th what is difference between sourcing and exporting variable ?

PS: i saw declaration of IFS in set command (IFS=$' \t\n')

What do you mean by all variables?

Incorrect. It writes the current environment to standard out.

set is a shell built-in to set and clear shell options. env writes the current environment to standard out.

Yes and no. Depends on your shell. What shell are you using?

  1. "set" lists all variables. Double check, your variable must be there.
    Try this:
 
aassdd="blabla" (or set aassdd="blabla")
echo $aassdd
set | grep aassdd
  1. "env" list all environment variables.

  2. For variable with space use quotes.

 
    qq="aaa                  vvv"
    echo $qq       # output will be ==> aaa vvv
    echo "$qq"     # output will be ==> aaa                  vvv
  1. For $IFS do the same as before:
 
    set | grep "$IFS"

Why use grep? It may give a lot more than the value of IFS:

$ set | grep IFS
DIFS=$' \t\n'
IFS=$' \t\n'
oldIFS=$' \t\n'
    oldIFS=$IFS;
    IFS=" -./";
    IFS=$oldIFS;
    IFS=:;
    oldIFS=$IFS;
    IFS=":";
    IFS=$oldIFS;
            printf "%s\n" "$IFS" "$OLD_IFS" 1>&2
            oldIFS
            newIFS
    local IFS=.;
    local IFS=.;
        IFS=$NL;
    IFS=" $TAB$NL";
newIFS () 
    if [ -n "${IFS+X}" ]; then
        OLD_IFS=${OLD_IFS}SET:$IFS;
        IFS=$1;
        OLD_IFS=${OLD_IFS}UNSET;
oldIFS () 
    case $OLD_IFS in 
            unset IFS
            IFS=${OLD_IFS##*SET:};
            OLD_IFS=${OLD_IFS%SET:*}
        IFS=: eval "printf \"%s\n\" \$PATH";

All you need is:

printf 'IFS=%s\n" "$IFS"
1 Like

Thanks for reply i am trying to do for loop in bash script throught *.mp3 files. Problem is that the mp3 files contains white spaces so i found this advice

http://www.unix.com/shell-programming-scripting/42839-preventing-whitespace-delimiter-loop-bash-sh.html

in short: back up IFS then set IFS to IFS=$�\n�, but how can i print current value of IFS ? echo $IFS gives me nothing. Thanks

Sorry an error. It should read as:

set | grep "^IFS"

In bash, at least, set with no parameters displays all environment variables and shell variables, even arrays.

You dont have to set IFS for that I think.
All that you need is to quote the variable.
It will be easier if you post the code here.
Dont echo $IFS
Just give the command as mentioned below to list it out.

 set | grep "^IFS"

OK i put code here, just simple for loop and print line containing white spaces

#!/bin/bash
for i in $(ls | awk '{print "\""$0"\""}'); do
    echo -ne "file {$i}\n"
done

names with white spaces are printed like:

file{"one}
file{long}
file{name"}

i want:

file {"one long name"}

also tried to quote

ls | awk '{print "\""$0"\""}'

inf for loop but did not work according expectations. Also awk i tried i thought it may help with quotes but did not.

 
ls -1 s* | sed 's/.*/file \{"&"\}/'

yes i can do that this way but if i want to use mv or cp in my script how do this. Thes works because of sed's & which is actual line. But i am interesting how to force bash for loop just skipping to new value just after recieving new line not any whitespace

Always double check before you click on "Submit Reply".
Check if there are mistakes.
Make sure others can understand what you are trying to say.
Write shorter sentences.
If possible, post the input and the expected output.
If your requirements have changed, mention that.

Can you please clearly state what you want?
I am not sure if this is what you are looking for:

ls -1 s* | sed 's/.*/cp "&" "&.cpy"/' | ksh

All files starting with a "s" will be copied with extension ".cpy"
I am not sure why you need a loop.

I am sorry if i typed something which is un clearly. I have followings files in directory

-rw-r--r-- 1 marek marek 0 2009-07-31 20:37 01 - album - track001.mp3
-rw-r--r-- 1 marek marek 0 2009-07-31 20:37 02 - album - track002.mp3
-rw-r--r-- 1 marek marek 0 2009-07-31 20:37 03 - album - track003.mp3
-rw-r--r-- 1 marek marek 0 2009-07-31 20:37 04 - album - track004.mp3
-rw-r--r-- 1 marek marek 0 2009-07-31 20:37 05 - album - track005.mp3
-rw-r--r-- 1 marek marek 0 2009-07-31 20:37 06 - album - track006.mp3
-rw-r--r-- 1 marek marek 0 2009-07-31 20:37 07 - album - track007.mp3
-rw-r--r-- 1 marek marek 0 2009-07-31 20:37 08 - album - track008.mp3
-rw-r--r-- 1 marek marek 0 2009-07-31 20:37 09 - album - track009.mp3

what i am trying to do is rename to trackXXX.mp3

I found that can be done with

for jmeno in *.mp3
do
  cp $jmeno /tmp/`echo $i | sed "s/\([0-9]\{2\}\).*/track0\1.mp3/"`
done

but did not work for me. Also i searched and found that i have to change IFS variable.
Can you please advise me if this task can be done using using bash and for loop (not ksh), i am traying to learn something about bash scripting. Thanks

Something like this?

ls *.mp3 | awk '{system("cp " $0 " " $NF)}'

I've used the cp command but you can replace it with the mv command.

Regards

Print all variables - local and global.

set 

Print global(=environment) variables. Child process get copy of global variables, but not locals.

env

What is locals ? set - env

How to make global variable ? Use export command.

export variable

How to remove variable ?

unset variable

How to look ex. IFS value, IFS include some special characters ? Example:

echo -n "$IFS" | od -c

IFS default value is "white space" = space+tab+newline

Using special characters. Example IFS is TAB+backspace+hex 02+newline

IFS=$'\t\b\x02\n' 

One solution for your needs =remove all chars before ex. track007.mp3
= remove "07 - album - ". Space before string track.

#!/bin/ksh
#!/bin/bash

for f in *.mp3
do
    # remove all chars before last space including last space
    new="${f##* }"
    [ "$new" != "$f" ] && mv "$f" "$new"
done

Did not work for me

cp: target `track001.mp3' is not a directory
cp: target `track002.mp3' is not a directory
cp: target `track003.mp3' is not a directory
cp: target `track004.mp3' is not a directory
cp: target `track005.mp3' is not a directory
cp: target `track006.mp3' is not a directory
cp: target `track007.mp3' is not a directory
cp: target `track008.mp3' is not a directory
cp: target `track009.mp3' is not a directory

thanks anyway

I am trying something more bit complicated:

#!/bin/bash
#IFS=$'\n'
echo default IFS:
echo -n "$IFS" | od -a -b
IFS=$'\n'
echo new IFS:
echo -n "$IFS" | od -a -b
for x  in `ls *.mp3`
do
 echo "`sed -ne 's/\([0-9]\{2\}\) - .* - .*[0-9]\{3\}\.mp3/track\1.mp3/gp' $x`"
done
echo new IFS:
echo -n "$IFS" | od -a -b
unset IFS
echo standard IFS:
echo -n "$IFS" | od -a -b

but alsdo did not work, IFS is set to newline, sed command must be OK because if i try it outside script everything works. Now i tryed just echo output of sed but nothing appears.

also tried replace echo with

cp "$x" "`sed -ne 's/\([0-9]\{2\}\) - .* - .*[0-9]\{3\}\.mp3/track\1.mp3/gp' $x`"

but according expectation it do nothing.

Also i am noticed something strange

numbers="$(printf "\n")"; echo -n "$numbers" | od -a -b
0000000

numbers="$(printf "\t")"; echo -n "$numbers" | od -a -b
0000000  ht
        011
0000001

Can someone explain that ???

PS i am total bash scripting newbie, sorry for dummmy questions

If all that you are trying to do is just rename the file,
then this is a simple and straight solution.

ls -1 | sed 's/.*\(track.*$\)/cp "&" \1/' | ksh

Doesthis solve your issue?
Or is it necessary it has to be done your way?

I tried that but did not work this is error:

ksh[1]: 01: not found [No such file or directory]
ksh[2]: 02: not found [No such file or directory]
ksh[3]: 03: not found [No such file or directory]
ksh[4]: 04: not found [No such file or directory]
ksh[5]: 05: not found [No such file or directory]
ksh[6]: 06: not found [No such file or directory]
ksh[7]: 07: not found [No such file or directory]
ksh[8]: 08: not found [No such file or directory]
ksh[9]: 09: not found [No such file or directory]

Thanks anyway.

I am very interesting what is wrong with my script, for and sed works but when i put it together it does nothing.

The -1 as an argument to ls is pointless if you are piping the result.

Anyway:

for file in *.mp3 ; do
      mv "$file" "${file##* }"
done

Not that it affects the command in any way, but yes, the "-1" is not required.
I generally prefer 1 liner to run on the prompt and most of the requests are for that.
But, I do like your approach too.

---------- Post updated at 09:51 PM ---------- Previous update was at 09:37 PM ----------

Are you sure you gave the quotes in the "&"?
Ok. First try this and see what comes out:

ls *track* | sed 's/.*\(track.*$\)/cp "&" \1/'

If that looks good then try this:

ls *track* | sed 's/.*\(track.*$\)/cp "&" \1/' | ksh

But if you are not looking for an one liner, then the codeby Reborg looks more simpler.