What's the "right" way to do the following as a boolean expression?
for i in `ls $1/resources`; do
if [ $i != "database.db" ]
then
if [ $i != "tiles" ]
then
if [ $i != "map.pdf" ]
then
if [ $i != "map.png" ]
then
svn export -q $1/resources/$i ../MyProject/Resources/$i
...
The other solutions have a couple of common mistakes:
http://www.pixelbeat.org/programming/shell_script_mistakes.html
for i in $(ls ...) is redundant/problematic
just do: for i in $1/resources*; do ...
[ $i != file1 -a $1 != file2 ] This actually has 2 problems.
a. The $i is not quoted, hence names with spaces will cause issues
b. -a is inefficient if stating files as it doesn't short circuit (I know the above is not stating files).
So instead try:
for i in $1/resources/*; do
if [ "$i" != "database.db" ] &&
[ "$i" != "tiles" ] &&
[ "$i" != "map.pdf" ] &&
[ "$i" != "map.png" ]; then
svn export -q "$i" "../MyProject/Resources/$(basename $i)"
fi
done
Even shorter:
for i in `ls $1/resources`; do
if [ $i != databse.db -a $i != titles -a $i != map.pdf ]; then
svn export -q $1/resources/$i ../MyProject/Resources/$i
fi
done;
The -a in the if expression is the equivalent of the boolean AND in shell-tests. For more see man test
Consider using a case statement:
for i in $(ls $1/resources); do
case $i in
database.db|tiles|map.pdf|map.png)
;;
*)
svn export -q $1/resources/$i ../MyProject/Resources/$i;;
esac
done
for i in `ls $1/resources`; do
if [ $i != "database.db" ] && [ $i != "tiles" ] && [ $i != "map.pdf" ] && [ $i != "map.png" ]; then
svn export -q $1/resources/$i ../MyProject/Resources/$i
For future reference, the new [[ test operator is preferred. The accepted answer is close and everything mentioned applies, but that answer will require lots of quoting and calls to multiple tests.
The preferred method would be something like:
for i in $1/resources/*; do
if [[ $i != "database.db" && $i != "tiles" &&
$i != "map.pdf" && $i != "map.png" ]]; then
svn export -q "$i" "../MyProject/Resources/$(basename $i)"
fi
done
Related
I want to list project directory all xcworkspace and xcodeproj file.
And I write code below
#!/bin/bash
workspaceFile="xcworkspace"
projectFile="xcodeproj"
#listFiles
path=$(pwd)
fileList=()
walk_dir () {
for name in "$path"/*; do
if [[ -d "$name" && ("${name##*.}" != ${projectFile} || "${name##*.}" != ${workspaceFile}) ]]; then
path=$name
walk_dir "$name"
else
if [ "${name##*.}"x = ${workspaceFile}x ] || [ "${name##*.}"x = ${projectFile}x ];then
fileList+=($name)
fi
fi
done
}
walk_dir
for name in ${fileList[#]}; do
echo $name
done
It did not work.
But If change the condition, like below
if [[ -d "$name" && ("${name##*.}" != ${workspaceFile}) ]]; then
path=$name
walk_dir "$name"
else
if [ "${name##*.}"x = ${workspaceFile}x ] || [ "${name##*.}"x = ${projectFile}x ];then
fileList+=($name)
fi
fi
or
if [[ -d "$name" && ("${name##*.}" != ${projectFile}) ]]; then
path=$name
walk_dir "$name"
else
if [ "${name##*.}"x = ${workspaceFile}x ] || [ "${name##*.}"x = ${projectFile}x ];then
fileList+=($name)
fi
fi
It works also.
I want to keep filter xcworkspace and xcodeproj.
Someone can help me?
Finaly, I found result by myself.
#!/bin/bash
workspaceFile="xcworkspace"
projectFile="xcodeproj"
path=$1
fileList=()
projectList () {
for name in "$path"/*; do
if [ -d "$name" ] && [ "${name##*.}"x = ${workspaceFile}x ]; then
fileList+=(${name})
elif [ -d "$name" ] && [ "${name##*.}"x = ${projectFile}x ]; then
fileList+=(${name})
elif [ -d "$name" ]; then
path=$name
projectList
fi
done
}
projectList
for name in ${fileList[#]}; do
echo "xcode project: $name"
done
I am trying to write an if statement where it will go to the next iteration of the for loop if i is the variable or if i is a directory. I am struggling with the directory part which would go after the -o
for i in *
if [ "$i" = VARIABLE -o ]
then
continue
fi
I don't fully understand the question, but a common idiom is:
for i in *; do
if test -d "$i"; then continue; fi
...
done
If you also want to compare against a particular value, you really shouldn't use -o. It's been deprecated for a long time. Instead, use:
if test -d "$i" || test "$i" = VARIABLE; then ...
You can use test -d:
if [ "$i" = VARIABLE ] || ! [ -d "$i" ]
then continue
fi
Or more succinctly:
[ "$i" != VARIABLE ] && [ -d "$i" ] || continue
Or as separate tests:
[ "$i" != VARIABLE ] || continue
[ -d "$i" ] || continue
How is it possible to get an URL parameter like /?photo=1.png into a shell script as a variable, running into a cgi-bin container on apache?
Edit
Iam generating a list of all files in a directory.
#!/bin/bash
echo "Content-type: text/html"
echo
for file in /var/www/html/export/tui/*;
do
echo "<a href='/cgi-bin/test.cgi?file="${file: -27}"'>"${file: -27}"</a><br>";
done;
Now, i want to give the file name as a parameter into a second script, who needs this for reading it.
I found a solution who take the URL parameter and give it into my script
#!/bin/bash
echo "Content-type: text/html"
echo
function cgi_decodevar()
{
[ $# -ne 1 ] && return
local v t h
t="${1//+/ }%%"
while [ ${#t} -gt 0 -a "${t}" != "%" ]; do
v="${v}${t%%\%*}" # digest up to the first %
t="${t#*%}" # remove digested part
if [ ${#t} -gt 0 -a "${t}" != "%" ]; then
h=${t:0:2}
t="${t:2}"
v="${v}"`echo -e \\\\x${h}`
fi
done
echo "${v}"
return
}
function cgi_getvars()
{
[ $# -lt 2 ] && return
local q p k v s
case $1 in
GET)
[ ! -z "${QUERY_STRING}" ] && q="${QUERY_STRING}&"
;;
POST)
cgi_get_POST_vars
[ ! -z "${QUERY_STRING_POST}" ] && q="${QUERY_STRING_POST}&"
;;
BOTH)
[ ! -z "${QUERY_STRING}" ] && q="${QUERY_STRING}&"
cgi_get_POST_vars
[ ! -z "${QUERY_STRING_POST}" ] && q="${q}${QUERY_STRING_POST}&"
;;
esac
shift
s=" $* "
while [ ! -z "$q" ]; do
p="${q%%&*}"
k="${p%%=*}"
v="${p#*=}"
q="${q#$p&*}"
[ "$1" = "ALL" -o "${s/ $k /}" != "$s" ] && \
export "$k"="`cgi_decodevar \"$v\"`"
done
return
}
cgi_getvars BOTH ALL
echo $foo
I have the following humble zsh function:
function remember()
{
if [ "$1" != "" ]
then
if[ "$1" != "clean" ]
then
echo "Why";
#echo $1 >> {~/.remember_info};
else
rm -r ~/.remember_info;
touch ~/.remember_info;
fi
else
cat .remember_info;
fi
}
When I try to source it I get:
parse error near `echo' (The echo being the line with echo "Why";)
The error is quite non descriptive and I assume its related to part of the loop's logic (since no matter what instruction I give after then it error out there).
Is there any way to "debug" this kind of thing ? zsh -n doesn't help much (at all)
You forgot the space between if and [ when comparing to clean.
This is case, though, where your function can be made simpler by handling the = case first.
function remember()
{
if [ "$1" = "" ]; then
cat ~/.remember_info
elif [ "$1" = clean ]; then
rm -r ~/.remember_info
touch ~/.remember_info
else
echo "$1" >> ~/.remember_info;
fi
}
Or, use a case statement.
remember () {
f=~/.remember_info
case $1 in
"")
cat "$f"
;;
clean)
rm -r "$f"
touch "$f"
;;
*)
print "$1" >> "$f"
;;
esac
}
You are missing a whitespace after [. It should be:
function remember()
{
if [ "$1" != "" ]
then
if [ "$1" != "clean" ]
then
echo "Why";
#echo $1 >> {~/.remember_info};
else
rm -r ~/.remember_info;
touch ~/.remember_info;
fi
else
cat .remember_info;
fi
}
[ is the same as test. It is a separate command, described in man test:
TEST(1)
NAME
test - check file types and compare values
SYNOPSIS
test EXPRESSION
test
[ EXPRESSION ]
[ ]
[ OPTION
I am trying to validate users input to a small script I am writing that checks that there should be: 2 arguments and the the first argument should be wither 'mount' or ' unmount'
I have the following:
if [ ! $# == 2 ] || [ $1 != "mount" -o $1 != "unmount" ]; then
However it seems to be a bit overzelouse at meeting the conditions I want. For example with the current || operator, nothing gets past the validator but if I use the && operator everything does.
if [ ! $# == 2 ] && [ $1 != "mount" -o $1 != "unmount" ]; then
Can someone help me figure this out?
Here is the whole block and intended usage
if [ ! $# == 2 ] || [ $1 != "mount" -o $1 != "unmount" ]; then
echo "Usage:"
echo "encmount.sh mount remotepoint # mount the remote file system"
echo "encmount.sh unmount remotepoint # unmount the remote file system"
exit
fi
You could do it like this:
if [ "$#" -ne 2 ] || [ "$1" != "mount" -a "$1" != "unmount" ]; then
echo "Usage:"
echo "encmount.sh mount remotepoint # mount the remote file system"
echo "encmount.sh unmount remotepoint # unmount the remote file system"
exit -1
fi
echo "OK"
You have a small logical error in your test, since you should enter the usage branch if $1 is not equal to both "mount" and "unmount". Also you should compare numbers with the -eq and -ne operators (see here), or use the (( )).
Note that you should quote your variables inside a test ([ ])
You can also combine the two expressions like this:
if [ "$#" -ne 2 -o \( "$1" != "mount" -a "$1" != "unmount" \) ]; then
If you have bash, you can also use the [[ ]] syntax:
if [[ $# -ne 2 || ( $1 != "mount" && $1 != "unmount" ) ]]; then