Bash read -p doesnt work [duplicate] - linux

This question already has answers here:
': not a valid identifier [duplicate]
(4 answers)
Why would a correct shell script give a wrapped/truncated/corrupted error message? [duplicate]
(1 answer)
Closed 5 years ago.
When running my shell script I get this error:
': not a valid identifiere 17: read: `
Here is my shell script:
#!/usr/bin/env bash
# Mr. Robot Install Wordpress Script
# Script is used for the following:
# add user to server
# change to new user home directory
# download latest version of wordpress
# unzip wordpress
# move all files up a directory level
# move up a directory level
# delete wordpress.zip
# remove wordpress folder
echo "/*****************************************************/"
echo "/************** HELLO MR. ROBOT **********************/"
echo "/*****************************************************/"
echo ".."
echo ".."
echo "Website URL"
echo 'url: \r'
read -p $website
echo 'User: \r'
read -p $newuser
echo 'Pass: \r'
read -p $password
echo "creating account......"
/scripts/wwwacct $website $newuser $password 0 x3 n n n 0 0 0 0 0 0
echo "Changing Directory....."
cd ~/home/$newuser/
echo "Getting Latest Version of Wordpress!"
curl -O http://wordpress.org/latest.tar.gz
echo "Tarball Incoming!!"
tar xvzf latest.tar.gz
echo "removing tar file"
rm latest.tar.gz
echo "moving wordpress folders!"
cp -a ~/home/$newuser/public_html/wordpress/. ~/home/$newuser/public_html/
cd /home/$newuser/public_html/
echo "Part 01 Complete!!"
exit
I've tried to use different versions of the read line with -p or -e. Any help would be appreciated. I've even tried adding it on a separate line with input.
EDIT: Updated file to where it takes inputs, but issue is that the inputs are not being used through the rest of the script. Thus causing errors for directories not being found.

Don't quote the variables names. read needs the name of the variable to assign to, not its value, which is what you get if you have a dollar sign $.
read -p 'website url: ' website
read -p 'Username: ' newuser
read -p 'Password: ' password
It looks like one of the variables holds \r, a carriage return. The error message that bash is trying to print is something like:
bash: ./script: line 17: read: `\r': not a valid identifier
But \r causes the cursor to go back to the beginning of the line, causing ': not a valid identifier to overwrite the beginning of the message.

As mentioned above by John Kugelman, in case you have to check if you Input_file is having carriage returns then you could run following command:
cat -v Input_file
In case you find them then try to remove them from either of following cmmands:
tr -d '\r' < Input_file
OR
awk '{gsub(/\r/,"")} 1' Input_file
Or check if your system(box) has dos2unix utility you could use that also for removing these carriage returns.

Related

Increment the title of files output by a command in a shell script

I made this simple bash script to take a full-screen screenshot and save it to the pictures folder
#!/usr/bin/bash
xfce4-screenshooter -f -s /home/rgcodes/Pictures/Screenshot_$scrshotcount.png
let "scrshotcount++"
...which runs into a problem. scrshotcount is a global variable I defined in /etc/environment to be incremented every time the script runs. However, the script fails to increment the variable globally, and causes the script to just overwrite the previous screenshot. Searches on Google and Stack Overflow revealed that the problem isn't straightforward at all (something about child shells being unable to change variables for parents), and finding some other method would be better.
Here's my question. How do we append numbers (in ascending order) to the screenshots the script throws out so that they are saved just like those taken on Windows?(Windows auto-suffixes matching filenames, rather than overwriting them, so all Screenshots have the same name 'Screenshot' and the number of times the screenshot command has been used.)
I am using #erikMD's method as a temporary stop-gap for now.
In addition to the excellent advice about using a date instead of a counter, here's a way to use a counter :/
dir=$HOME/Pictures
# find the current maximum value
current_max=$(
find "$dir" -name Screenshot_\*.png -print0 \
| sort -z -V \
| tail -z -n 1
)
if [[ ! $current_max =~ _([0-9]+)\.png ]]; then
echo "can't find the screenshot with the maximum counter value" >&2
exit 1
fi
# increment it
counter=$(( 1 + ${BASH_REMATCH[1]} ))
# and use it
xfce4-screenshooter -f -s "$dir/Screenshot_${counter}.png"
You'll have to manually create the Screenshot_1.png file.
#rgcodes below is a script that will capture screenshots with a numeric count indicator per your original post. (tested it on Ubuntu 20.04)
Script contents:
#!/bin/bash
set -uo pipefail
# add source file and line number to xtrace output
# i.e. when running: bash -x ./your_script_name.sh
export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }'
capture_screenshot() {
local output_dir="${1:-/tmp/screenshot}"
local img_name="${2:-Screenshot}"
local img_ext="${3:-png}"
# create output directory (if not already existing)
mkdir -p "${output_dir}"
# get the last image in the sorted ls output
local latest_png=$(tail -n 1 \
<(sort -n -t _ -k 2 \
<(ls ${output_dir}/*.${img_ext} 2> /dev/null)))
# use the latest image to determine img_cnt value for next image
local img_cnt=0
if [[ ${latest_png} =~ _([0-9]+)\.png ]]; then
img_cnt=$((1+${BASH_REMATCH[1]}))
elif [[ ${latest_png} =~ ${img_name}.${img_ext} ]] ; then
img_cnt=1
fi
# build path to output image
local img_path="${output_dir}/${img_name}_${img_cnt}.${img_ext}"
# remove count from output image path if count == 0
if [[ "${img_cnt}" -eq "0" ]] ; then
img_path="${output_dir}/${img_name}.${img_ext}"
fi
xfce4-screenshooter -f -s "${img_path}"
}
capture_screenshot "$#"
The uses the following as defaults, but you can change them to meet your requirements.
output directory for screenshots:
/tmp/screenshot
base screenshot image name:
Screenshot
screenshot file extension:
.png
The script will attempt to create the output directory if it does not already exist (subject to user permission for creation). Below is a sample usage.
Prior to initial script execution, the output directory does not exist:
$ ls screenshot
$
Initial execution (directory is created and Screenshot.png created:
$ ./script.sh
$ ls /tmp/screenshot/
Screenshot.png
Subsequent executions:
$ ./script.sh
$ ls /tmp/screenshot/
Screenshot_1.png Screenshot.png
$ ./script.sh
$ ls /tmp/screenshot/
Screenshot_1.png Screenshot_2.png Screenshot.png
Indeed, as suggested by #j_b in the comments, you should definitely give a try to using a timestamp with the command date +"$format".
FTR, the same idea is implemented here in this project of a gnome-screenshot bash wrapper
(disclaimer: I am the author of this repo).
Example command:
date "+%Y-%m-%d_%H-%M-%S"
↓
2021-07-29_19-13-30
So the overall script could just be something like:
#!/usr/bin/env bash
xfce4-screenshooter -f -s "$HOME/Pictures/Screenshot_$(date "+%Y-%m-%d_%H-%M-%S").png"
(Note that I added missing double-quotes, and modified your shebang, as /usr/bin/env bash is more portable than /bin/bash or /usr/bin/bash.)

Problem when using the ssh-copy-id command in script

I write this for add SSH connection from the list automatically but when I run this script have error! I think this problem relate to read ip from $line variable in script.
My Script:
#!/bin/bash
filename='iplist.txt'
n=1
USER=root
SSHPASS=123456
while read line; do
echo "No. $n : IP = $line"
echo "yes \n" | sshpass -p "$SSHPASS" \
ssh-copy-id -o StrictHostKeyChecking=no $USER#$line \
&& echo "Add successfully!" || echo "FAILED"
echo "########################################"
n=$((n+1))
sleep 2
done < $filename
iplist.txt is a file that's contain my IPs:
172.25.25.1
172.25.25.2
This is the result of my script:
No. 1 : IP = 172.25.25.1
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
: Name or service not known: ssh: Could not resolve hostname 172.25.25.1
FAILED
########################################
No. 2 : IP = 172.25.25.2
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
: Name or service not known: ssh: Could not resolve hostname 172.25.25.2
FAILED
########################################
check the file endings, if they are CRLF for windows, CR for mac, or LF for linux.
while read -r line; do COMMAND; done
The -r option passed to read command prevents backslash escapes from being interpreted.
Add IFS= option before read command to prevent leading/trailing whitespace from being trimmed -
while IFS= read -r line; do COMMAND_on $line; done
the code above is an example, you may want to use the -r parameter. For IFS you probably do not want to use this, because if there was any whitespace, then IFS would keep this and not remove them.

Get substring from Start Index to End Index

I'm working on this for two hours but no luck, always the "Bad substitution" error.
What I want to make (.sh script):
Read from file (names), then I'd like to substitute this name with substring of the given name by the offset and lenght which are the script arguments ($1 = offset, $2 = lenght).
It should work like this (I think) : new_user=${user:$1:$2}
-> where user is read from .txt (in while loop) and $1 and $2 are arguments of this .sc
I've highlighted the important part:
#!/bin/bash
touch postopek.log
while IFS="," read fullName userName passwordLarge
do
pass=$(perl -e 'print crypt(&ARGV[0], "password")' $passwordLarge)
new_up=${fullName:$1:$2} # important line
sudo useradd -m -p $pass -d /home/$new_up -s /bin/bash $new_up
[ $? -eq 0] && echo "Made something bla bla not important..." >> postopek.log
sudo mkdir /home/$new_up/gradivo
sudo cp -r /home/administrator/vaje/* /home/$new_up/gradivo
sudo chown -R $new_up:$new_up /home/$new_up/gradivo
done < /home/administrator/seznam.txt
The sh shell you are running the script with is probably not bash, try running it like
bash ustvari.sh 3 5
or just
/path/to/ustvari.sh 3 5
since your shebang points to bash anyway.
${parameter:offset:length} is not specified by POSIX, thus if your /bin/sh is a shell which does not support the substring syntax, you get the Bad substitution error you encountered, for example:
$ dash
$ echo ${foo:0:1}
dash: 1: Bad substitution

Error With Bash Script [duplicate]

This question already has answers here:
Are shell scripts sensitive to encoding and line endings?
(14 answers)
Closed 3 years ago.
I would like to know what is the error in the below script
i get error as : command not foundh: line 1: , : command not foundh: line 2: its continuous
i have tried add ; but now working kindly tell me what to do ??
#!/bin/bash;
clear;
FILEREPO=http://192.168.1.2/cpplugin;
echo "-----------------------------------------------";
echo " Welcome to C-Panel Login Alert Installer";
echo "-----------------------------------------------";
cd /var/cpanel/;
mkdir perl5
cd perl5/
mkdir lib
cd lib/
wget $FILEREPO/LoginAlerthook.zip
unzip LoginAlerthook.zip
rm -r LoginAlerthook.zip
cd /
/usr/local/cpanel/bin/manage_hooks add module LoginAlert
chmod 777 LoginAlert.pm
echo " "
echo " Login Alert Script Hooked With C Panel Finished"
echo " "
The fact that you're getting the funny output is a sure bet that your script has carriage return (CR) characters at the end of the lines, usually a symptom of using Windows editors that assume line endings should be CR/LF rather than just the standard UNIX LF (linefeed). That is causing error output like:
this_command_ends_hh<CR>: command not found
and because the CR is putting the cursor back at line start, it's overwriting some of it:
this_command_ends_hh<CR>
: command not found
making:
: command not foundh
Examine your script with od -xcb scriptname to check for CR (displayed as \r) characters, you can also pipe the script output through od -xcb to see the real output. For example is a file I created with hello followed by a carriage return on the one and only line:
0000000 6568 6c6c 0d6f 000a
h e l l o \r \n
150 145 154 154 157 015 012
0000007
You can see the CR (\r) in there.
If that is the problem, simply remove the CR characters such as piping it through tr -d '\r'.
Executing cat hello.txt | tr -d '\r' | od -xcb shows that you can get rid of it:
0000000 6568 6c6c 0a6f
h e l l o \n
150 145 154 154 157 012
0000006
In your case, assuming your script is called freak.bash, you would use:
tr -d '\r' <freak.bash >newfreak.bash
and newfreak.bash would be the one without the offending characters.
A tool you can use to understand what is happening in the execution of this script in order to debug is the command,
bash -x scriptname.sh
paxdiablo is almost certainly correct: you need to fix the line endings. But you also have an errant semi-colon in the first line. Instead of:
#!/bin/bash;
you want:
#!/bin/bash
without the trailing semi-colon.
I don't have a Centos 5 right now, but maybe... just maybe... bash isn't located at /bin? In FreeBSD, it's located at /usr/local/bin. In Cygwin, it's at /usr/bin. What's the output of this command:
which bash
paxdiablo and William Pursell nicely explained what the problem is.
Now, please take the time to improve your script if you're going to distribute it.
NOT TESTED example:
#/bin/bash
ZIPFILE=http://192.168.1.2/cpplugin/LoginAlerthook.zip
CPANEL_LIBDIR=/var/cpanel/perl5/lib
MANAGE_HOOKS_CMD=/usr/local/cpanel/bin/manage_hooks
TMPFILE=`tempfile`
function exit_with_error(){
echo "$*" >&2 # Write error messages to stderr!!
exit 1
}
function at_exit(){
[ -f "${TMPFILE}" ] && rm -v ${TMPFILE}
}
# Run at_exit function when script finishes
trap at_exit 0
echo "WELCOME TO ZOMBO.COM"
# Create lib directory if not exists, exit if not possible
if ! [ -d "${CPANEL_LIBDIR}" ]; then
mkdir -p ${CPANEL_LIBDIR} || exit_with_error "Couldn't create required directory [${CPANEL_LIBDIR}]"
fi
wget ${ZIPFILE} -O ${TMPFILE} || exit_with_error "Couldn't download file"
unzip -d ${CPANEL_LIBDIR} ${TMPFILE} || exit_with_error "Couldn't unzip file"
chmod +x ${CPANEL_LIBDIR}/LoginAlert.pm || exit_with_error "Couldn't chmod file"
$MANAGE_HOOKS_CMD add module LoginAlert
echo "End."
This is just a dirty example. Read the manpages to improve.
man bash
man tempfile
man wget
man unzip
man chmod

Remove in linux

hey so I have some code for the question bellow but I am stuck its not working and I don't really know what I am doing.
This script should remove the contents of the dustbin directory.
If the -a option is used the script should remove ALL files from the dustbin.
Otherwise, the script should display the filenames in the dustbin one by one and ask the user for confirmation that they should be deleted
#!/bin/sh
echo " The files in the dustbin are : "
ls ~/TAM/dustbin
read -p " Please enter -a to delete all files else you will be prompted to delete one by one : " filename
read ans
if ["filename" == "-a"]
cat ~/TAM/dustbin
rm -rf*
else
ls > ~/TAM/dustbin
for line in `cat ~/TAM/dustbin`
do
echo "Do you want to delete this file" $line
echo "Y/N"
read ans
case "ans" in
Y) rm $line ;;
N) "" ;;
esac
EDITED VERSION
if test ! -f ~/TAM/dustbin/*
then
echo "this directory is empty"
else
for resfile in ~/TAM/dustbin/*
do
if test -f $resfile ; then
echo "Do you want to delete $resfile"
echo "Y/N"
read ans
if test $ans = Y ; then
rm $resfile
echo "File $resfile was deleted"
fi
fi
done
fi
this works however Now I get one of 2 errors either
line 4 requires a binary operator or line 4: to many arguments
I see one obvious mistake:
rm -rf*
when it should be
rm -rf *
to be asked about every file deletion - add -i key
rm -rfi *
Many problems here:
A space missing before the * in rm. The space is needed so the shell can recognize the wildcard and expand it.
Do you really want to remove all the files in the current directory? If not, specify the path rm -rf /path/to/files/* or cd into the directory, preferably with cd /path/to/files || exit 1.
I do not understand the logic of the script. You show a dustbin, but if the user gives -a, you overwrite it with all the non-hidden files (ls > dustbin). Is that what you want?
First of all, case "ans" of just matches a string "ans" to other strings, which is obviously false, you need case $ans of to get the value of variable ans. if ["filename" == "-a"] is also comparison between two strings, which is always false. The first parameter of a script can be accessed as $1 (the second as $2 and so on).
Please read man 1 sh to get the basics of shell programming (all of the above notes can be found there).

Resources