Click to See Complete Forum and Search --> : problem with for loop in BASH
i have some code to ftp all files in a directory using curl, and it is not doing what i am expecting.
i originally had this:
#!/bin/bash
for filename in "$(ls)" ; do
echo -e "Transferring : $filename\n"
curl -T $filename -u username:password ftp://server.com/public_html/
echo -e "\n"
done
and it worked except for an error when it hit a directory name - which i expected.
i wanted to stop it from attempting to ftp directories and give an error so i now have the following code:
#!/bin/bash
for filename in "$(ls)" ; do
if ! [ -d "$filename" ]; then
echo -e "Transferring : $filename\n"
curl -T $filename -u username:password ftp://server.com/public_html/
echo -e "\n"
fi
done
and it doesn't work.
i get this for output:
Transferring : images
index.html
nvidia.html
proftpd.html
ss1.html
ss2.html
ss3.html
curl: (6) Couldn't resolve host 'index.html'
curl: (6) Couldn't resolve host 'nvidia.html'
curl: (6) Couldn't resolve host 'proftpd.html'
curl: (6) Couldn't resolve host 'ss1.html'
curl: (6) Couldn't resolve host 'ss2.html'
curl: (6) Couldn't resolve host 'ss3.html'
curl: (25) Failed FTP upload: images: No such file or directory.
:confused: :confused: :confused:
sploo22
08-12-2003, 06:56 PM
I'm baffled too; but try changing the very first line to
#!/bin/bash -x
That should print out all of the commands that are executed, and maybe shed some more light on this problem.
it looks like it is trying to pass all the files in the directory at once instead of each one individually.
im sure it's a subtle syntax error of some sort.
hopefully bwkaz comes on soon - he will know what i am doing wrong :)
hmmm.... now my original code doesn't work. i must have changed something else.....
</me bangs head against wall>
sploo22
08-12-2003, 07:49 PM
Well, one thing you could do is replace $(ls) with * in your loop condition; I'm not sure if that would help, but it's worth a try. If you want to recurse through subdirectories, change it to $(find . -type f).
does the exact same thing unfortunately.
it's trying to put all the files at once sparated by a single space as the variable instead of each one separately and iterate through them.
for some odd reason, this works:#!/bin/bash
files=$(ls)
for filename in $files ; do
if ! [ -d "$filename" ]; then
echo -e "Transferring : $filename\n"
curl -T $filename -u username:password ftp://server.com/public_html/
echo -e "\n"
fi
done
if someone sees this and can tell me why the origianal code doesn't work and this does i'd be grateful.
Ath0s
08-12-2003, 09:34 PM
I think you need to remove the " from around the $(ls)
With the " it grabs the entire result at once, instead of seperating it into
individual files ...
Hope that helps,
(EDIT) I checked it with this simple script:
for i in "$(ls)"; do echo "next: $i"; done
compared to this:
for i in $(ls); do echo "next: $i"; done
ah cool! thanks. i'll try that later. i knew it was a simple syntax thing.
chrism01
08-13-2003, 11:03 AM
i always use
for files in `ls -1`
ie one file per line. Works just fine. :)
Originally posted by Hayl
ah cool! thanks. i'll try that later. i knew it was a simple syntax thing.
the final script - which now accepts options looks like this:
#!/bin/bash
# /usr/bin/ftp_directory
# Written by: DKD dale_d at telusplanet dot net
#
# Requires: curl
#
# Purpose: FTPs all files in the current directory to
# the specified server and path
#
# Usage: ftp_directory -f ftp://<servername>/<path>/ -u <username> -p <password>
# (NOTE: must have a trailing / on the path or curl will fail)
#
# Get user options
while getopts ":f:u:p:" opt;
do
case $opt in
f) ftp_server="$OPTARG" ;;
u) user_name="$OPTARG" ;;
p) password="$OPTARG" ;;
?) echo 'USAGE: ss.sh -i image_name -f ftp_server -u user_name -p password'
exit 1
esac
done
# iterate through all filenames in the current directory,
# skip subdirectories, use curl to ftp each file
for filename in $(ls) ; do
if ! [ -d "$filename" ]; then
echo -e "Transferring : $filename\n"
curl -T $filename -u $user_name:$password $ftp_server
echo -e "\n"
fi
done
CaptainPinko
10-04-2003, 03:21 AM
i'm just looking ata book and i'm trying to follow the syntax but
#! /usr/bin/bash
for CASH in 1.99 30.00 0.99 0.01
do
{
echo $CASH
}
done
doesn't do jack. thats pretty much the syntax in the book
for VAR in LIST
do
{ body }
done
am i missing something is that pretty much the same?
bwkaz
10-04-2003, 09:06 AM
bash is at /bin/bash, not /usr/bin/bash (your first line).
And I've never seen the curly braces before. They're definitely not needed (though I don't think they'd cause any problem).
CaptainPinko
10-04-2003, 01:26 PM
Originally posted by bwkaz
And I've never seen the curly braces before. They're definitely not needed (though I don't think they'd cause any problem).
reallllllly? my book has them everywhere....
and yeah i typed the wrong path at the top
bwkaz
10-04-2003, 05:15 PM
Check the bash manpage (though you'll have to search through it for quite a while...). Curly braces are only used to group commands (they act like parentheses, which execute the group of commands in a subshell, except they don't use a subshell).
But the "for" builtin doesn't need the loop body grouped at all; it executes every command between "do" and "done". Like I said, I don't think it'd mess anything up, it's just not strictly needed.
So I assume that once you fixed that path, the script worked? Because I can copy and paste it here, and it does...
CaptainPinko
10-05-2003, 12:31 AM
aye, it worked. i'm not quite sure which fixed it but it works now