View previous topic :: View next topic |
Author |
Message |
fourhead l33t
Joined: 03 Sep 2003 Posts: 875 Location: Cologne, Germany
|
Posted: Sat Oct 29, 2005 3:21 pm Post subject: Need help with a little script |
|
|
Hi, I was searching for a way to sync to dirs, and I found a little script for this (rsync won't work for different reasons). The problem is, this script doesn't handle filenames with spaces in them, a file 'name with space.txt' is treating as three files. I believe the problem is with the ls command. Could somebody help me make this script work with such filenames?
Code: |
#! /bin/bash
# if [ diff "$1" "$2" ]; then echo falsch; fi
# echo "extended diff"
echo dir: $1 vergleichen mit: $2
for fn in $( ls $1 ); do
# echo Dateiname: "$fn"
if [ -f "$2/$fn" ]; then
diff -q $1/$fn $2/$fn
#echo rv: $?
if (( $? == 0 )); then
#echo touch
touch -r $2/$fn $1/$fn
else
cp -ruv $2/$fn $1/$fn.0
fi
elif [ -d "$2/$fn" ]; then
touch -r $2/$fn $1/$fn
/root/bin/t3 "$1/$fn" "$2/$fn"
# else echo nicht gefunden
fi
done
|
I'd really appreciate your help, it's a little urgent and I really have no idea of bash scripting.
Tom |
|
Back to top |
|
|
truc Advocate
Joined: 25 Jul 2005 Posts: 3199
|
Posted: Sat Oct 29, 2005 3:26 pm Post subject: |
|
|
I would write "$something" instead of $something .
Please, let me know if it works |
|
Back to top |
|
|
Earthwings Bodhisattva
Joined: 14 Apr 2003 Posts: 7753 Location: Germany
|
Posted: Sat Oct 29, 2005 3:33 pm Post subject: |
|
|
Won't work. There are two things you have to keep in mind when dealing with filenames with spaces in bash:
First, when using filenames in a for loop, be careful.
will work fine as the filename expansion is a bash builtin that handles spaces correctly.
Code: | for file in $(ls *.jpg) | will not work out of the box, as the default IFS contains spaces as well, i.e. bash breaks the filenames returned by the ls command in several strings when they contains spaces. You can set IFS to newline only to make that work.
Second, when passing filenames with spaces to mv/cp etc., quote them as outlined by truc.
There are other utilities than rsync to sync directories. unison for example, or some thing that works remotely over http or ftp IIRC. _________________ KDE |
|
Back to top |
|
|
fourhead l33t
Joined: 03 Sep 2003 Posts: 875 Location: Cologne, Germany
|
Posted: Sun Oct 30, 2005 12:42 pm Post subject: |
|
|
@earthwings
I understand what you mean, but would there be a way to make
Code: |
for fn in $( ls $1 ); do
|
aware of filenames with spaces in them? Would it help to use ls -l instead, so that every filename is in a single row? I tried rsync, and as I said its only a bad solution for several reasons, and this script would actually do exactly what I need, it would be perfect, it's just this problem with filenames.
Tom |
|
Back to top |
|
|
ac_static n00b
Joined: 11 Oct 2005 Posts: 45 Location: Ontario, Canada
|
Posted: Sun Oct 30, 2005 12:59 pm Post subject: |
|
|
You can always modify how bash determines word separation by doing something like:
Code: |
OLDIFS=$IFS
IFS=$'\n' # set IFS to newline only.
# do whatever
IFS=$OLDIFS
#done.
|
|
|
Back to top |
|
|
fourhead l33t
Joined: 03 Sep 2003 Posts: 875 Location: Cologne, Germany
|
Posted: Mon Oct 31, 2005 11:40 am Post subject: |
|
|
Thanks for your tip, but I solved it a little different now. The script looks like this:
Code: |
#! /bin/bash
#echo dir: $1 vergleichen mit: $2
cd $1
for fn in *
do
echo Dateiname: $fn
#echo "$2/$fn"
if [ -f "$2/$fn" ]; then
diff -q "$fn" "$2/$fn" > /dev/null
#echo rv: $?
if (( $? == 0 )); then
echo touch
touch -r "$2/$fn" "$fn"
else
echo bkup copy
cp -ruv "$2/$fn" "$fn".0
fi
elif [ -d "$1/$fn" ]; then
touch -r "$2/$fn" "$fn"
/root/bin/t6 "$1/$fn" "$2/$fn"
else
echo nicht gefunden
fi
done
|
But there's a problem with this script. No matter if the compared files are identical or not ($? is '0' or '1') they're always touched. I've tested it with 10 files, 3 of them different, and on the 7 identical files I see the output 'rv: 0', the 3 changed files cause an output 'rv: 1', which should be correct, but still, only the 'then' argument is executed, not the 'else' (the bkup copy thing). I have no idea why - is there a Bash scipting expert out there ?????
Tom |
|
Back to top |
|
|
Cocker68 Apprentice
Joined: 16 Jan 2003 Posts: 227 Location: Germany
|
Posted: Mon Oct 31, 2005 1:52 pm Post subject: |
|
|
fourhead wrote: | But there's a problem with this script. No matter if the compared files are identical or not ($? is '0' or '1') they're always touched. | This is because Your successful echo-command sets $? to 0. You have to keep the return code in a separate Variable.
I reworked Your script a little bit:
Code: | #!/bin/bash
SCRIPT=`basename $0`
DIR1="$1"
DIR2="$2"
#echo "$SCRIPT: compare $DIR1 with $DIR2"
[ -d "$DIR1" -a -d "$DIR2" ] || exit 1
# scan DIR1 for files
for NAME in "$DIR1"/*; do
# we just use the filename here
NAME=`basename "$NAME"`
echo "$SCRIPT: Name1: $DIR1/$NAME"
#echo "$SCRIPT: Name2: $DIR2/$NAME"
if [ -f "$DIR2/$NAME" ]; then
# this is a file
diff -q "$DIR1/$NAME" "$DIR2/$NAME" > /dev/null
RET=$?
#echo "$SCRIPT: return value of diff: $RET"
if [ $RET -eq 0 ]; then
echo "$SCRIPT: touching the file"
touch -r "$DIR2/$NAME" "$DIR1/$NAME"
else
echo "$SCRIPT: backup-copy of file"
cp -ruv "$DIR2/$NAME" "$DIR1/${NAME}.0"
fi
elif [ -d "$DIR1/$NAME" ]; then
# this is a directory
echo "$SCRIPT: touching the directory"
touch -r "$DIR2/$NAME" "$DIR1/$NAME"
/root/bin/t6 "$DIR1/$NAME" "$DIR2/$NAME"
else
echo "$SCRIPT: don't know how to handle"
fi
done |
- Cocker :wq |
|
Back to top |
|
|
|