You are not logged in.

#1 2007-10-24 09:24:54

tfp
Member
Registered: 2007-10-11
Posts: 16

if in shell ?

Hi Arch-friends,
I'm sorry if this is the wrong part of the forum for that topic. Please move it if that's the case smile

I got a problem:
I've written a shellscript which should copy a few files but I always get the same error, I don't know what to do against it:
[nils@nils ~]$ ./skript
./skript: line 11: syntax error near unexpected token `then'
./skript: line 11: ` if [[ -f $i ]]; then pfad2=`basename $i`;'

Line 11 says:
if [[ -f $i ]]; then pfad2=`basename $i`;
When I remove the if-condition, the shell says:
./skript: line 5: #: command not found
./skript: line 9: for: command not found
./skript: line 10: do: command not found
basename: missing parameter
„basename --help" will give further information
./skript: line 13: pf ad2=: command not found
./skript: line 16: #: command not fou nd
./skript: line 17: mv: command not fo und
pattern mnt/festplatte/serien 2 in mnt/festplatte/serien not found
./skript: line 21: done: command not found

I think the first message is the strangest. Why is he trying to interprete the # ?
Here the whole script:

#!/bin/sh
topics=( party birthday holiday );
for j in $topics;
do pfad=mnt/festplatte/$j;
  # old
  altifs=$IFS;
  # space doesn't separate arrays
  IFS=`echo -en "\n\t"`;
  for i in `find /mnt/festplatte/NEU -maxdepth 1 -print0 -iname '*$j*'`;
          do
                  if [[ -f $i ]]; then pfad2=`basename $i`;
                          pfad2=${pfad2%.*};
                  else pfad2={i%/*};
                  fi;
                  # move the found videos to the right directory and remove the sources
                  mv $i $pfad;
          if [ $pfad/*$pfad2*.src == $pfad/\*$pfad2\*.src ];
            then echo "Pattern $pfad 2 not found in $pfad";
          else find $pfad -type f -maxdepth 1 -iname '*$pfad2*.src' -print0 | xargs -0 rm; fi;
          done;
done;
unset j; unset i; unset themen; unset pfad; unset pfad2;
IFS=$altifs;
#IFS=`echo -en "\n\t "`;
echo "Rest:";
find /mnt/festplatte/NEU;

Could somebody please tell me why it isn't working ?

Thank you in advance

Last edited by tfp (2007-10-24 09:27:14)

Offline

#2 2007-10-24 10:06:38

lang2
Member
Registered: 2006-02-10
Posts: 386

Re: if in shell ?

It is probably not suitable for this section alright but here is my answer:
your file is probably in DOS format.
To fix this, you can do dos2unix or in Vim, do :set ff=unix and :w

Offline

#3 2007-10-24 10:13:10

tfp
Member
Registered: 2007-10-11
Posts: 16

Re: if in shell ?

lang2 wrote:

It is probably not suitable for this section alright but here is my answer:
your file is probably in DOS format.
To fix this, you can do dos2unix or in Vim, do :set ff=unix and :w

Which file do you mean ? The scriptfile ?

Offline

#4 2007-10-24 10:26:09

lang2
Member
Registered: 2006-02-10
Posts: 386

Re: if in shell ?

Yes.

Offline

#5 2007-10-24 13:30:27

Dusty
Schwag Merchant
From: Medicine Hat, Alberta, Canada
Registered: 2004-01-18
Posts: 5,986
Website

Offline

#6 2007-10-24 14:01:05

klixon
Member
From: Nederland
Registered: 2007-01-17
Posts: 525

Re: if in shell ?

The examples in the bash reference manual all look like this:

if test-commands; then # note the new line after then
  consequent-commands;
[elif more-test-commands; then # here it is again
  more-consequents;]
[else alternate-consequents;]
fi

(I added the comments though...)

Have you tried splitting "if [[ -f $i ]]; then pfad2=`basename $i`;" into two lines? as in

if [[ -f $i ]]; then 
    pfad2=`basename $i`;
fi

`basename $i` is old form btw. Better get used to the new style as the old will disappear (and the new one nests better):

$( basename $i )

try this

#!/bin/sh
topics=( party birthday holiday )
for j in $topics; do 
  pfad=mnt/festplatte/$j
  # old
  altifs=${IFS}
  # space doesn't separate arrays
  IFS=$( echo -en "\n\t" )
  for i in $( find /mnt/festplatte/NEU -maxdepth 1 -print0 -iname '*$j*' ); do
    if [ -f $i ]; then 
      pfad2=$( basename $i )
      pfad2=${pfad2%.*}
    else
      pfad2=${i%/*}
    fi
    # move the found videos to the right directory and remove the sources
    mv $i ${pfad}
    if [ ${pfad}/*${pfad2}*.src == ${pfad}/\*${pfad2}\*.src ]; then
      echo "Pattern ${pfad2} not found in ${pfad}"
    else 
      find ${pfad} -type f -maxdepth 1 -iname '*${pfad2}*.src' -print0 | xargs -0 rm
    fi
  done
done
unset j; unset i; unset themen; unset pfad; unset pfad2
IFS=${altifs}
#IFS=$( echo -en "\n\t " )
echo "Rest:"
find /mnt/festplatte/NEU

Last edited by klixon (2007-10-24 14:20:36)


Stand back, intruder, or i'll blast you out of space! I am Klixon and I don't want any dealings with you human lifeforms. I'm a cyborg!

Offline

#7 2007-10-24 15:00:38

tfp
Member
Registered: 2007-10-11
Posts: 16

Re: if in shell ?

I did all three suggestions:
:set ff=unix and :w in gvim,
I inserted newlines after every then and I replaced the basename $i line with "pfad2=`$(basename $i)`;"
but still the same error:
[nils@nils ~]$ ./script
./script: line 11: syntax error near unexpected token `then'
./script: line 11: `                  if [[ -f $i ]]; then'

I also tried to copy and paste the text into a new file and execute that one. It gives me the same error.
Nothing seems to work. I start getting despaired. What should I do to get this working ?

Last edited by tfp (2007-10-24 15:03:25)

Offline

#8 2007-10-24 15:07:08

tfp
Member
Registered: 2007-10-11
Posts: 16

Re: if in shell ?

Now I am getting confused.
I opy and pasted the version klixon posted and it doesn't give me an error (besides he doesn't find anything... gotta work with that)
but I don't get the difference what I did wrong

Got the bug: He doesn't separate anything of the found files. He treads all found files as one file and so mv fails. But I got filenames with spaces in it. Does anyone know how to fix that problem ?

Last edited by tfp (2007-10-24 15:11:51)

Offline

#9 2007-10-24 16:40:43

tfp
Member
Registered: 2007-10-11
Posts: 16

Re: if in shell ?

I tried to split the long string with gawk. But when I run this script nothing happens and it seems to run forever. Is there an infinite loop ?

Current version:

#!/bin/sh
topics=( party birthday holiday )
for j in $topics; do 
  pfad=/mnt/festplatte/$j
  # old
  altifs=${IFS}
  # space doesn't separate arrays
  IFS=$( echo -en "\n\t" )
  for i in ` find /mnt/festplatte/NEU -maxdepth 1 -mindepth 1 -print0 -iname "*$j*" `; do
    gawk '{split ($i, dateien," ")}';
    for l in $dateien; do
        if [ -f $l ]; then 
          pfad2=$( basename $l )
          pfad2=${pfad2%.*}
        else
          pfad2=${l%/*}
        fi
        # move the found videos to the right directory and remove the sources
        mv $l $pfad
        if [ $pfad/*$pfad2*.src == $pfad/\*$pfad2\*.src ]; then
          echo "Pattern $pfad2 not found in $pfad"
        else 
          find $pfad -type f -maxdepth 1 -iname '*$pfad2*.src' -print0 | xargs -0 rm
        fi
     done
  done
  IFS=${altifs}
done
unset j; unset i; unset topics; unset pfad; unset pfad2; unset l
#IFS=$( echo -en "\n\t " )
echo "Rest:"
find /mnt/festplatte/NEU

Offline

#10 2007-10-24 18:57:26

klixon
Member
From: Nederland
Registered: 2007-01-17
Posts: 525

Re: if in shell ?

The thing you did wrong was you did

if <condition>; then <action>

this should be either

if <condition>; then
  <action>

The newline after "then" is not optional
allas, i have no time yet to look at the contents of the script, just the structure, maybe later toninght, or tomorrow wink


Stand back, intruder, or i'll blast you out of space! I am Klixon and I don't want any dealings with you human lifeforms. I'm a cyborg!

Offline

#11 2007-10-24 19:33:37

tam1138
Member
Registered: 2007-09-10
Posts: 238

Re: if in shell ?

Yeah, not so much.  Bash programs are completely newline-agnostic.  To wit:

pete@vingilot:~/tmp $ cat ./test.sh 
#!/bin/sh

if (exit 0) ; then echo yay ; fi
pete@vingilot:~/tmp $ ./test.sh 
yay

tfp, the first problem I see with your script is your use of single quotes around *$j* in the find command.  Single-quotes in bash prevent variable interpolation; that is, find is looking for a file named, literally, *$j* as opposed to *party*, *birthday*, or *holiday*, as you intend.  I think the if-statement is bombing because that find is returning something unexpected.  Specifically, I'm not sure bash tokenizes the output of find -print0 nicely.  You're trying to accommodate files with spaces in their names, presumably, but I believe the -print0 option is intended for use with xargs -0.  Your alternative is to do something like this:

find . -iname "*$j*" | while read filename; do
    if [[ -f "$filename" ]]; then
        do stuff
    fi
done

Note that a newline is an acceptable alternative to a semi-colon.  (Yes, it *is* newline-agnostic, as I said, but newlines *can* be used as statement breaks.)  Note also that you could instead use [ ] rather than [[ ]], but that's ticky-tacky. smile

Hopefully this will work for you.

Last edited by tam1138 (2007-10-24 19:34:32)

Offline

#12 2007-10-24 19:57:28

tfp
Member
Registered: 2007-10-11
Posts: 16

Re: if in shell ?

Thanks. Now I don't get any error.
But in the Rest there are files with birthday in its name left...
Why ? (directories and files haven't been moved)

PS: I also removed the lines with IFS from the script

find /mnt/festplatte/NEU -maxdepth 1 -mindepth 1 -iname "*birthday*"

returns 4 directories and they weren't moved by the script and were returned as rest.

find /mnt/festplatte/NEU -maxdepth 1 -mindepth 1 -iname "*holiday*"

returns 2 files and 2 directories which weren't moved. Only the first part of the array at
the beginning was moved successfully.  sad

But at least the script starts to begin a bit of what I want it to do. Thank you guys

Last edited by tfp (2007-10-24 20:03:09)

Offline

#13 2007-10-24 19:58:54

Cerebral
Forum Fellow
From: Waterloo, ON, CA
Registered: 2005-04-08
Posts: 3,108
Website

Re: if in shell ?

Well, the same reason applies for your single quotes around this line:

find $pfad -type f -maxdepth 1 -iname '*$pfad2*.src' -print0 | xargs -0 rm

- did you switch those for double-quotes too?

Offline

#14 2007-10-24 20:06:51

tfp
Member
Registered: 2007-10-11
Posts: 16

Re: if in shell ?

Cerebral wrote:

Well, the same reason applies for your single quotes around this line:

find $pfad -type f -maxdepth 1 -iname '*$pfad2*.src' -print0 | xargs -0 rm

- did you switch those for double-quotes too?

Currently the script looks like that:

#!/bin/sh
topics=( party birthday holiday )
for j in $topics; do 
  pfad=/mnt/festplatte/$j/
  find /mnt/festplatte/NEU -maxdepth 1 -mindepth 1 -iname "*$j*"| while read i; do
        if [ -f $i ]; then 
          pfad2=$( basename $i )
          pfad2=${pfad2%.*}
        else
          pfad2=${i%/*}
        fi
        # move the found videos to the right directory and remove the sources
        mv $i $pfad
        if [ $pfad/*$pfad2*.src == $pfad/\*$pfad2\*.src ]; then
          echo "Pattern $pfad2 not found in $pfad"
        else 
          find $pfad -type f -maxdepth 1 -iname "*$pfad2*.src" -print0 | xargs -0 rm
        fi
  done
done
unset j; unset i; unset topics; unset pfad; unset pfad2;
echo "Rest:"
find /mnt/festplatte/NEU -mindepth 1 -maxdepth 1

I got another question also: Is there a way to put an echo output to a file and to stdout
with one command ?

Offline

#15 2007-10-24 20:21:51

Cerebral
Forum Fellow
From: Waterloo, ON, CA
Registered: 2005-04-08
Posts: 3,108
Website

Re: if in shell ?

man tee

Offline

#16 2007-10-24 21:08:41

tam1138
Member
Registered: 2007-09-10
Posts: 238

Re: if in shell ?

It will help me help you if I understand exactly what it is you're trying to do.  Please verify whether this description is accurate: You have a bunch of files and directories in /mnt/festplatte/NEU, from which you want to select only those files and directories which contain the substring "party", "birthday", or "holiday".  For each such file or directory found, move it to a subdirectory named after the matching substring.  Finally, remove all .src files where the prefix (ie, everything before the last dot) matches the prefix of a file or directory that has been moved.  Is that correct?

Offline

#17 2007-10-24 21:11:52

tam1138
Member
Registered: 2007-09-10
Posts: 238

Re: if in shell ?

The reason the other files aren't being moved is because "for" doesn't work on arrays.  Example:

pete@vingilot:~ $ foo=(bar baz bat)
pete@vingilot:~ $ for i in $foo; do echo $i ; done
bar

Rather, you want a space-delimited list:

pete@vingilot:~ $ foo="bar baz bat"
pete@vingilot:~ $ for i in $foo; do echo $i ; done
bar
baz
bat

That fix will probably make your script work.  But I have a feeling there is a better way to do it than what you've got now; if you're interested in learning philosophical correctness as opposed to just functional correctness, let us know. wink

Last edited by tam1138 (2007-10-24 21:12:35)

Offline

#18 2007-10-24 22:03:04

MrWeatherbee
Member
Registered: 2007-08-01
Posts: 277

Re: if in shell ?

tam1138 wrote:

The reason the other files aren't being moved is because "for" doesn't work on arrays.  Example:

pete@vingilot:~ $ foo=(bar baz bat)
pete@vingilot:~ $ for i in $foo; do echo $i ; done
bar

Or, maybe it can (but not really smile):

#!/bin/bash

foo=(bar baz bat)
numarrayelements=${#foo[@]}

for i in $( seq $numarrayelements ); do
    echo ${foo[(($i-1))]}
done

Output of the above:

bar
baz
bat

Last edited by MrWeatherbee (2007-10-24 22:05:38)

Offline

#19 2007-10-24 23:53:11

Cerebral
Forum Fellow
From: Waterloo, ON, CA
Registered: 2005-04-08
Posts: 3,108
Website

Re: if in shell ?

Well, for arrays, I usually just use

for i in ${array[@]}; do

Offline

#20 2007-10-25 06:13:26

tfp
Member
Registered: 2007-10-11
Posts: 16

Re: if in shell ?

What the script should do:
I got files and directories in /mnt/festplatte/NEU named diffently but they got party, birthday, or holiday in its name. They should be moved to /mnt/festplatte/bithday/, /mnt/festplattey/holiday/ , and to /mnt/festplatte/party. And in each of those folders are files named similar to the ones which should be moved but they have the ending .src. These files should be erased. But he may only erase the file which to belongs to the file/directory which is moved. So if it is a file I remove the ending and then i try to find the file named similar but with the ending src. Because the files are only named similar it is possible that he can't find the files manually so I have to look it up myself (that's why he has to print which patterns he didn't find).

But if the output gets to long or I have no time I won't see it. so I also want to write this output to a file. Is it right to replace the line
echo "Pattern $pfad2 not found in $pfad"
with
tee "Pattern $pfad2 not found in $pfad" files.log
?

And when he has done all that, I would like to see the rest(it is possible that there are files in /mnt/festplatte/NEU which don't include any of the above in their name).

What is the way the script would be better but doing the same ?

Offline

#21 2007-10-31 19:46:10

tfp
Member
Registered: 2007-10-11
Posts: 16

Re: if in shell ?

I got one last problem.
He doesn't move any files with spaces in it sad
Anyone got a work-around ?

I also get some errors:
./script: line 6: [: too many arguments
pattern /mnt/festplatte/NEU not found in /mnt/festplatte/birthday      (it is a whole wrong pattern ! it should be the name of the file which is moved...)
mv: call of stat for „/mnt/festplatte/NEU/birthday" not possible: file or directory not found

and some more but they are the same only with other files (for every file with spaces in its name i get these 3 errors and he doesn't move any of these)

#!/bin/sh
themen="party birthday holiday"
for j in $themen; do 
  pfad=/mnt/festplatte/$j/
  find /mnt/festplatte/NEU -maxdepth 1 -mindepth 1 -iname "*$j*"| while read i; do
        if [ -f $i ]; then 
          pfad2=$( basename $i )
          pfad2=${pfad2%.*}
        else
          pfad2=${i%/*}
        fi
        # move the found videos to the right directory and remove the sources
        mv $i $pfad
        if [ $pfad/*$pfad2*.src == $pfad/\*$pfad2\*.src ]; then
          echo "pattern $pfad2 not found in $pfad"|tee -a fehler
        else 
          find $pfad -type f -maxdepth 1 -iname "*$pfad2*.torrent" -print0 | xargs -0 rm
        fi
  done
done
unset j; unset i; unset themen; unset pfad; unset pfad2;
echo "Rest:"
find /mnt/festplatte/NEU -mindepth 1 -maxdepth 1

Offline

#22 2007-10-31 20:08:01

tam1138
Member
Registered: 2007-09-10
Posts: 238

Re: if in shell ?

On lines 6 and 13, enclose $i in double-quotes.

Offline

#23 2007-11-02 06:41:23

tfp
Member
Registered: 2007-10-11
Posts: 16

Re: if in shell ?

tam1138 wrote:

On lines 6 and 13, enclose $i in double-quotes.

Thank you very much, that did the trick.
And I found another mistake: Line 10 has to be pfad2=${i##*/}.

Now it works the right way.


Thanks to all who helped me and also thanks to all who tried to help me

Offline

Board footer

Powered by FluxBB