I'm trying to get a shell script to take values. What I currently have is:
#!/system/bin/sh
echo "Enter the page numbers"
read page_no_first;
read page_no_final;
#
echo $page_no_first
echo $page_no_final
The echos are simply there for debug, and the problem is that they display as blanks.
The terminal results are as such:
scriptname
Enter the page numbers
1
1
5
5
Verbatim. That is the echo commands simply produce two empty lines.
I've found a sort of work around, and another related problem:
#!/system/bin/sh
echo "Enter the page numbers"
read page_no_first -s
read page_no_final -s
#
echo $page_no_first
echo $page_no_final
This should give me the read without it repeating the input. Instead, what it gives me is:
scriptname
Enter the page numbers
1
1
: is readonlyriptname[3]: read: -s
3
3
: is readonlyriptname[3]: read: -s
1
3
Ironically, this successfully writes the numbers to the variables, however, it a) does not give me a silent read, and b) gives me some funny error. Googling it doesn't help, since it's too vague.
Any help?
This work as expected (at least as I think it should):
#! /system/bin/sh
echo "Enter the page numbers"
echo -n "First: "
read page_no_first
echo -n "Last: "
read page_no_last
echo "First: $page_no_first Last: $page_no_last"
on android 4.2
Related
I'm writing a simple Bash script that simply the call of HadnBrakeCli for render videos.
I also implemented a simple queue option: the queue file just store the line-command it has to call to start a render.
So I wrote a while-loop to read one line at time, eval $line and repeat untill file ends.
if [[ ${QUEUE_MODE} = 'RUN' ]]; then
QUEUE_LEN=`cat ${CONFIG_DIR}/queue | wc -l`
QUEUE_POS='1'
printf "Queue lenght:\t ${QUEUE_LEN}\n"
while IFS= read line; do
echo "--Running render ${QUEUE_POS} on ${QUEUE_LEN}..."
echo "++" && echo "$line" && echo "++"
eval "${line}"
tail -n +2 "${CONFIG_DIR}/queue" > "${CONFIG_DIR}/queue.tmp" && mv "${CONFIG_DIR}/queue.tmp" "${CONFIG_DIR}/queue"
echo "--Render ended"
QUEUE_POS=`expr $QUEUE_POS + 1`
done < "${CONFIG_DIR}/queue"
exit 0
The problem is that any command makes the loop to work fine (empty line, echo "test"...), but as soon a proper render is loaded, it is launched and finished correctly, but also the loops exists.
I am a newbie so I tried some minor changes to see what effect I got, but nothing change the result.
I commented the command tail -n +2 "${CONFIG_DIR}/queue" > "${CONFIG_DIR}/queue.tmp" && mv "${CONFIG_DIR}/queue.tmp" "${CONFIG_DIR}/queue" or I added/removed IFS= in the while-loop or removed the -r in read command.
Sorry if the question is trivial, but I'm really missing some major part in how it works, so I have no idea even how to search for the solution.
I'll put a sample of a general render in the queue file.
HandBrakeCLI -i "/home/andrea/Videos/done/Rap dottor male e mini me.mp4" -o "/hdd/Render/Output/Rap dottor male e mini me.mkv" -e x265 -q 23 --encoder-preset faster --all-audio -E av_aac -6 dpl2 --all-subtitles -x pmode:pools='16' --verbose=0 2>/dev/null
HandBrakeCLI reads from standard input, which steals the rest of the queue file before read line can see it. My favorite solution to this is to pass the file over something other than standard input, like file descriptor #3:
...
while IFS= read line <&3; do # The <&3 makes it read from FD #3
...
done 3< "${CONFIG_DIR}/queue" # The 3< redirects the file into FD #3
Another way to avoid the problem is to redirect input to the HandBrakeCLI command:
...
eval "${line}" </dev/null
...
There's some more info about this in BashFAQ #89: I'm reading a file line by line and running ssh or ffmpeg, only the first line gets processed!
Also, I'm not sure I trust the way you're using tail to remove lines from the queue file as they're executed. I'm not sure it's really wrong, it just looks fragile to me. Also, I'd recommend using lower- or mixed-case variable names, since there are a bunch of all-caps names with special meanings, and re-using one of them by mistake can have weird consequences. Finally, I'd recommend running your script through shellcheck.net, as it'll make some other good recommendations.
[BTW, this question is a duplicate of "Bash script do loop exiting early", but that doesn't have any upvoted or accepted answers.]
Using adb shell to run commands on an android device, I get different results when running ls with or without a wildcard ( globbing, i.e * ).
When running ls without a wildcard, the last path is displayed properly. When running ls with a wildcard, the path is displayed with an : in the end of it for some reason. The actual file does not have a : in its path.
My issue is specifically with the last file: /data/data/com.kauf.wrapmyFaceFunphotoeditor/files/DV-com.com.kauf.wrapmyFaceFunphotoeditor-2020-05-17-17-44-30-DEBUG.txt:
it has an : in the end which isn't supposed to be there
Why does using a wildcard in ls add characters to the result path?
Edit, environment details: Windows 10 / Android 7, the code is running on sh. I've ran adb shell to get to this command prompt, and doing it in one line (i.e adb shell su -c ls ...) returns similar results, same for adb shell command ...; also clarified the question.
As described in Why you shouldn't parse the output of ls, ls's behavior is not always well-defined. It's generally safer to use NULs (if you don't have any control or knowledge of filenames) or newlines (if you have reason to be certain that filenames can't contain them) to directly delimit a list of values emitted by the shell. Consider, then:
# output is separated by NULs, which cannot possibly exist in filenames
printf '%s\0' /data/data/com.kauf.wrapmyfacefunphotoeditor/files/DV-*
...or...
# output is separated by newlines; beware of a file named DV-evil<newline>something-else
printf '%s\n' /data/data/com.kauf.wrapmyfacefunphotoeditor/files/DV-*
Note that if you're passing this through extra unescaping layers, it may be necessary to double up your backslashes -- if you see literal 0s or ns separating filenames in your output, that's evidence of same.
Note also that if no matching files exist, a glob will expand to itself, so you can get an output that contains only the literal string /data/data/com.kauf.wrapmyfacefunphotoeditor/files/DV-*; in bash this can be suppressed with shopt -s nullglob, but with /bin/sh (particularly the minimal busybox versions more likely to be available on Android) this may not be available. One way to work around this is with code similar to the following:
# set list of files into $1, $2, etc
set -- /data/data/com.kauf.wrapmyfacefunphotoeditor/files/DV-*
# exit immediately if $1 does not exist
if [ "$#" -le 1 ] && [ ! -e "$1" ]; then
exit
fi
# otherwise, print the list in our desired format
printf '%s\0' "$#"
I want to declare character variables and then write those variables one after the other in order to form a command. Example:
#!/system/bin/sh
tt=e;rr=c;uu=h;yy=o;
zz=i;ll=f;pp=n;cc=t
x=29
$zz$ll [ "$x"-eq 29 ]
$cc$uu$tt$pp
$tt$rr$uu$yy "yes"
$ll$zz
This code should read:
if [ "$x" -eq 29 ]
then
echo "yes"
fi
This works for the "echo" command but won't work for "if".
Always getting errors: if not found, then not found, fi not found.
I've tired surrounding with quotes and braces.
This is being done on android.
It turns out that i can achieve the desired outcome by utilizing the fact that echo will work regardless. so I echo the entire contents of the shell script in question (test.sh) and run commands in another bash instance reading from stdin.
Modified code now is
tt="e";rr="c";uu="h";yy="o";_1="i";ll="f";pp="n";cc="t"
x=29
"$1" "
$_1$ll [ "$x" -${tt}q 29 ]
$cc$uu$tt$pp
$tt$rr$uu$yy \"yes this file ran without error\"
$ll$_1
"
to run this:
/system/test.sh echo | sh -
This is really odd...
I can't get this test to result in true in my linux shell and I can't figure out why.
#!/bin/bash
a=$(adb shell getprop ro.product.brand)
adb shell getprop ro.product.brand
if [ "$a" == "Huawei" ]; then
echo "Success"
else
echo "Failed"
fi
The script just outputs:
Huawei
Failed
Whereas this script:
b=$(whoami)
whoami
if [ "$b" == "amo" ]; then
echo "Success"
else
echo "Failed"
fi
...outputs:
amo
Success
Can anyone help me understand that?
I already tried cutting away spaces or line breaks in $a by piping to cut or sed but I get the same result...
I suggest this as a way to remove leading/trailing whitespace :
# Trims $1
# If $2 supplied, assigns result to variable named $2
# If $2 not present, echoes the value to stdout
trim()
{
if
[[ $1 =~ ^[[:blank:]]*(.*[^[:blank:]])[[:blank:]]*$ ]]
then
local result="${BASH_REMATCH[1]}"
else
local result="$1"
fi
if
(( $# > 1 ))
then
printf -v "$2" %s "$result"
else
printf %s "$result"
fi
}
This function uses no external program, so has low overhead.
Maybe a quick explanation of the regular expression...
^[[:blank:]]*(.*[^[:blank:]])[[:blank:]]*$
It matches all leading and trailing whitespace (no surprise there)
In the middle, it matches any string of characters that ends with a non-blank and saves that as a sub-expression for access with BASH_REMATCH
If there were no "non-blank" character specified to end the middle portion, the greedy .* would eat everything up until the end of the string, including trailing blanks.
The .* is, on the other hand, certain to begin with a non-blank, because the greedy initial [[:blank:]]* will only stop when encountering a non-blank.
Depending on your need, you may also use [[:space:]] instead of [[:blank:]] (difference explained here : https://en.wikipedia.org/wiki/Regular_expression#Character_classes). Basically, [[:blank:]] matches tabs and spaces, and [[:space:]] also matches newlines, carriage returns, and a few more.
First, sorry if my question is obscure or in an inconvenient format. This is my first post here :D.
My issue is that I have a script, let's say test.sh which reads an input, and validates if it's a positive integer (reg ex used from this post:
BASH: Test whether string is valid as an integer?):
#!/bin/sh
echo -n " enter number <"
read num
if [[ $num =~ ^-?[0-9]+$ ]] #if num contains any symbols/letters
then # anywhere in the string
echo "not a positive int"
exit
else
echo "positive int read"
fi
I am running this script on my android device (Xiaomi Mi3 w) using adb shell and the error:
syntax error: =~ unexpected operator keeps displaying.
First, is my regex even correct?
Second, any hints on how I can overcome this syntax error?
The default shell in Android is mksh. It is not 100% compatible with bash. So do not expect all bash recipes to work without changes.
For the description of features supported by mksh - read its manual page.
This is a GNU bash POSIX regular expression. In Korn Shell, you can use extglob regular expressions to the same effect:
if [[ $num = ?(-)+([0-9]) ]]; then
…
See the section “File name patterns” in the manpage for details.
I had to use ksh expression as shown below to get this to work.
case $num in
+([0-9])*(.)*([0-9]) )
# Variable positive integer
echo "positive integer"
;;
*)
# Not a positive integer
echo "NOPE"
exit
;;
esac