How can I extract or fetch a domain name from a URL string (e.g. https://www.cyberciti.biz/index.php) using bash shell scripting under Linux or Unix-like operating system?
You can use standard Unix commands such as sed, awk, grep, Perl, Python and more to get domain name from URL. No need to write regex. It is pretty simple.
Let use see various commands and option to grab the domain part from given variable under Linux or Unix-like system.
Get domain name from full URL
Say your url name is stored in a bash shell variable such as $x:
x='https://www.dbsysnet.com/'
You can use the awk as follows:
echo "$x" | awk -F/ '{print $3}'
### OR ###
awk -F/ '{print $3}' <<<$x
Sample outputs:
www.dbsysnet.com
Extract domain name from URL using sed
Here is a sample sed command:
url="https://www.dbsysnet.com"
echo "$url" | sed -e 's|^[^/]*//||' -e 's|/.*$||'
Extract domain name from URL using bash shell parameter substitution
Another option is to use bash shell parameter substitution:
# My shell variable
f="https://www.cyberciti.biz/faq/copy-command/"
## Remove protocol part of url ##
f="${f#http://}"
f="${f#https://}"
f="${f#ftp://}"
f="${f#scp://}"
f="${f#scp://}"
f="${f#sftp://}"
## Remove username and/or username:password part of URL ##
f="${f#*:*@}"
f="${f#*@}"
## Remove rest of urls ##
f=${f%%/*}
## Show domain name only ##
echo "$f"
|
Shell script example
A shell script to purge urls from Cloudflare by matching domain name part:
#!/bin/bash
zone_id=""
api_key=""
urls="$@"
bon=$(tput bold)
boff=$(tput sgr0)
c=1
[ "$urls" == "" ] && { echo "Usage: $0 url"; exit 1; }
clear
echo "Purging..."
echo
for u in $urls
do
echo -n "${bon}${c}${boff}.${u}: "
## Get domain name ##
d="$(echo $u | awk -F/ '{ print $3}')"
## Set API_KEY, Email_ID, and ZONE_ID as per domain ##
case $d in
www.cyberciti.biz) zone_id="ID_1"; api_key="MY_KEY_1"; email_id="[email protected]";;
theos.in) zone_id="ID_2"; api_key="MY_KEY_2"; email_id="[email protected]";;
*) echo "Domain not configured."; continue;;
esac
## Do it ##
curl -X DELETE "https://api.cloudflare.com/client/v4/zones/${zone_id}/purge_cache" \
-H "X-Auth-Email: ${email_id}" \
-H "X-Auth-Key: ${api_key}" \
-H "Content-Type: application/json" \
--data "{\"files\":[\"${u}\"]}"
echo
(( c++ ))
done
echo
|
I want to find out how many times a word (say foo or an IP address) occurs in a text file using the grep command on Linux or Unix-like system?
You can use the grep command to search strings, words, text, and numbers for a given patterns. You can pass the -coption to grep command. It only shows the number of times that the pattern has been matched for each file.
Show the total number of times that the word foo appears in a file named bar.txt
The syntax is:
grep -c string filename
grep -c foo bar.txt
Sample outputs:
3
To count total number of occurrences of word in a file named /etc/passwd root using grep, run:
grep -c root /etc/passwd
To verify that run:
grep --color root /etc/passwd
Pass the -w option to grep to select only an entire word or phrase that matches the specified pattern:
grep -w root /etc/passwd
OR
grep -c -w root /etc/passwd
In this example only match a word being with root:
grep --color -w '^root' /etc/passwd
grep -c -w '^root' /etc/passwd
To show only the matching part of the lines.
grep -o 'root' /etc/passwd
grep -c -o 'root' /etc/passwd
Sample session:
Fig.01: Counting occurrence of words/strings using grep command
I type ‘find . -type d -iname foo -delete‘ command to find the foo directories and delete them. However, I am getting an error message that read as find: cannot delete './hourly.4/data/foo': Directory not empty on Linux server. How do delete directories based on find command output on Linux or Unix-like system?
The -delete option remove the DIRECTORY(ies), if they are empty. You need to use the -execoption to delete all directories and its contents. The syntax is as follows.
Find command syntax to delete dirs
Try:
find /dir/to/search/ -type d -name "dirName" -exec rm -rf {} +
OR
find /dir/to/search/ -type d -name "dirName" -exec rm -rf \;
Warning: Be careful with the rm command when using with find. You may end up deleting unwanted data.
Find will execute given command when it finds files or dirs. For example:
find . -type d -name "foo" -exec rm -rf {} +
OR
find . -type d -name "bar" -exec rm -rf "{}" \;
Sample outputs:
removed './daily.0/bar/.cache/motd.legal-displayed'
removed directory './daily.0/bar/root/.cache'
removed './daily.0/bar/.lesshst'
removed './daily.0/bar/.viminfo'
removed './daily.0/bar/.vim/.netrwhist'
removed directory './daily.0/bar/root/.vim'
removed './daily.0/bar/root/.bashrc'
removed './daily.0/bar/.ssh/authorized_keys'
removed directory './daily.0/bar/root'
removed directory './daily.0/bar/var/spool/cron/crontabs'
You can find directories that are at least four levels deep in the working directory /backups/:
find /backups/ -type d -name "bar" -depth +4 -print0 -exec rm -rf {} +
Find and xargs
The syntax is as follows to find and delete directories on Linux/Unix system:
## delete all empty dirs ##
find /path/to/dir/ -type d -empty -print0 | xargs -0 -I {} /bin/rm -rf "{}"
## delete all foo dirs including subdirs in /backups/
find /backups/ -type d -name "foo*" -print0 | xargs -0 -I {} /bin/rm -rf "{}"
The second command is secure and fast version as it deals with weird dir names such as:
I want to display a countdown before purging cache from CDN network. Is there an existing command to show a conuntdown from 30..1 as 30,29,28,…1 on Linux or Unix bash shell script?
There are various ways to show a countdown in your shell scripts.
First define your message:
msg="Purging cache please wait..."
Now clear the screen and display the message at row 10 and column 5 using tput:
clear
tput cup 10 5
Next you need to display the message:
echo -n "$msg"
Find out the length of string:
l=${#msg}
Calculate the next column:
l=$(( l+5 ))
Finally use a bash for loop to show countdown:
for i in {30..01}
do
tput cup 10 $l
echo -n "$i"
sleep 1
done
echo
Here is a complete shell script:
#!/bin/bash
# Purpose: Purge urls from Cloudflare Cache
# Author: Vivek Gite {www.cyberciti.biz} under GPL v2.x+
# --------------------------------------------------------
# Set me first #
zone_id="My-ID"
api_key="My_API_KEY"
email_id="My_EMAIL_ID"
row=2
col=2
urls="$@"
countdown() {
msg="Purging ${1}..."
clear
tput cup $row $col
echo -n "$msg"
l=${#msg}
l=$(( l+$col ))
for i in {30..1}
do
tput cup $row $l
echo -n "$i"
sleep 1
done
}
# Do it
for u in $urls
do
amp_url="${u}amp/"
curl -X DELETE "https://api.cloudflare.com/client/v4/zones/${zone_id}/purge_cache" \
-H "X-Auth-Email: ${email_id}" \
-H "X-Auth-Key: ${api_key}" \
-H "Content-Type: application/json" \
--data "{\"files\":[\"${u}\",\"${amp_url}\"]}" &>/dev/null && countdown "$u"
done
echo
|
You can run it as follows:
./script.sh url1 url2
POSIX shell version
From this post:
countdown()
(
IFS=:
set -- $*
secs=$(( ${1#0} * 3600 + ${2#0} * 60 + ${3#0} ))
while [ $secs -gt 0 ]
do
sleep 1 &
printf "\r%02d:%02d:%02d" $((secs/3600)) $(( (secs/60)%60)) $((secs%60))
secs=$(( $secs - 1 ))
wait
done
echo
)
|
It can be run as follows:
countdown "00:00:10" # 10 sec
countdown "00:00:30" # 30 sec
countdown "00:01:42" # 1 min 42 sec

How do I replace a string with another string in all files? For example, ~/foo directory has 100s of text file and I’d like to find out xyz string and replace with abc. I’d like to use sed or any other tool to replace all occurrence of the word.
The sed command is designed for this kind of work i.e. find and replace strings or words from a text file under Apple OX, *BSD, Linux, and UNIX like operating systems. The perl can be also used as described below.
sed replace word / string syntax
The syntax is as follows:
sed -i 's/old-word/new-word/g' *.txt
GNU sed command can edit files in place (makes backup if extension supplied) using the -i option. If you are using an old UNIX sed command version try the following syntax:
sed 's/old/new/g' input.txt > output.txt
You can use old sed syntax along with bash for loop:
#!/bin/bash
OLD="xyz"
NEW="abc"
DPATH="/home/you/foo/*.txt"
BPATH="/home/you/bakup/foo"
TFILE="/tmp/out.tmp.$$"
[ ! -d $BPATH ] && mkdir -p $BPATH || :
for f in $DPATH
do
if [ -f $f -a -r $f ]; then
/bin/cp -f $f $BPATH
sed "s/$OLD/$NEW/g" "$f" > $TFILE && mv $TFILE "$f"
else
echo "Error: Cannot read $f"
fi
done
/bin/rm $TFILE
|
A Note About Bash Escape Character
A non-quoted backslash \ is the Bash escape character. It preserves the literal value of the next character that follows, with the exception of newline. If a \newline pair appears, and the backslash itself is not quoted, the \newline is treated as a line continuation (that is, it is removed from the input stream and effectively ignored). This is useful when you would like to deal with UNIX paths. In this example, the sed command is used to replace UNIX path “/nfs/apache/logs/rawlogs/access.log” with “__DOMAIN_LOG_FILE__”:
#!/bin/bash
## Our path
_r1="/nfs/apache/logs/rawlogs/access.log"
## Escape path for sed using bash find and replace
_r1="${_r1//\//\\/}"
# replace __DOMAIN_LOG_FILE__ in our sample.awstats.conf
sed -e "s/__DOMAIN_LOG_FILE__/${_r1}/" /nfs/conf/awstats/sample.awstats.conf > /nfs/apache/logs/awstats/awstats.conf
# call awstats
/usr/bin/awstats -c /nfs/apache/logs/awstats/awstats.conf
|
The $_r1 is escaped using bash find and replace parameter substitution syntax to replace each occurrence of / with \/.
perl -pie Syntax For Find and Replace
The syntax is as follows:
perl -pie 's/old-word/new-word/g' input.file > new.output.file