You are not logged in.
Pages: 1
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
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
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
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
Yes.
Offline
moved to general programming
Offline
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
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
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
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
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
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
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.
Hopefully this will work for you.
Last edited by tam1138 (2007-10-24 19:34:32)
Offline
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.
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
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
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
man tee
Offline
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
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.
Last edited by tam1138 (2007-10-24 21:12:35)
Offline
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 ):
#!/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
Well, for arrays, I usually just use
for i in ${array[@]}; do
Offline
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
I got one last problem.
He doesn't move any files with spaces in it
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
On lines 6 and 13, enclose $i in double-quotes.
Offline
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
Pages: 1