How to iterate over files containing space in FreeBSD /bin/sh - sh

I am trying to actuate over a set of files that contain space using FreeBSD /bin/sh shell:
user#host:~/temp/2011 $ find . | grep '03-11'
./01jan/ES 03-11.txt
./02feb/ES 03-11.txt
./03mar/ES 03-11.txt
./04apr/ES 03-11.txt
./05may/ES 03-11.txt
user#host:~/temp/2011 $ for i in `find . | grep '03-11'`; do echo "$i"; done
./01jan/ES
03-11.txt
./02feb/ES
03-11.txt
./03mar/ES
03-11.txt
./04apr/ES
03-11.txt
./05may/ES
03-11.txt
While I would like to get:
user#host:~/temp/2011 $ find . | grep '03-11'
./01jan/ES 03-11.txt
./02feb/ES 03-11.txt
./03mar/ES 03-11.txt
./04apr/ES 03-11.txt
./05may/ES 03-11.txt
user#host:~/temp/2011 $ for i in `find . | grep '03-11'`; do echo "$i"; done
./01jan/ES 03-11.txt
./02feb/ES 03-11.txt
./03mar/ES 03-11.txt
./04apr/ES 03-11.txt
./05may/ES 03-11.txt
What shall be done to deal with the space in this case?

You need to set IFS to a value that does not include a space character.
For example:
(IFS=$'\n'; for i in `find . | grep '03-11'`; do echo "$i"; done)
See the manual page for details.

Some would fight hard for "the canonical Unix way of doing these kinds of things"
find . -type f | grep '03-11' | xargs -I {} echo {}

Related

Sh script to output unused interfaces on linux

I asked the dark side and here's what it printed.....
#!/bin/bash
for interface in $(ip addr show | awk '/^[0-9]+:/ {print $2}' | tr -d :)
do
if ! ip addr show $interface | awk '/inet / {print $2}' | grep -q . ; then
echo $interface
fi
done
I want to add n+ variable directly so the output will be the interfaces that is not used by the system,
Done
I have these two scripts, one for Linux and one for Mac, I hope they serve you because I have tested them on Linux Ubuntu and Mac.
on linux
#!/bin/bash
# This script will output unused interfaces on Linux
# Get list of all interfaces
interfaces=$(ifconfig -a | grep -o '^[^ ]*:' | tr -d :)
# Loop through each interface
for interface in $interfaces; do
# Check if interface is up
if [[ $(ifconfig $interface | grep -c 'UP') -eq 0 ]]; then
# Output interface name
echo "$interface is unused"
fi
done
on mac
#!/bin/bash
# Get list of all network interfaces
interfaces=$(networksetup -listallnetworkservices | tail -n +2)
# Loop through each interface
for interface in $interfaces; do
# Get the IP address of the interface
ip=$(ipconfig getifaddr "$interface")
# If the IP address is empty, the interface is unused
if [ -z "$ip" ]; then
echo "$interface is unused"
fi
done
#!/bin/bash
count=0
for interface in $(ip addr show | awk '/^[0-9]+:/ {print $2}' | tr -d :)
do
if ! ip addr show $interface | awk '/inet / {print $2}' | grep -q . ; then
free_interfaces[$count]=$interface
count=$((count + 1))
fi
done
case $count in
0)
echo "No usable interface found."
exit 1
;;
1)
DEFIF=${free_interfaces[0]}
echo "The interface $DEFIF will be used."
;;
*)
echo "Available interfaces to select: "
PS3="Press a number to select an interface to use (1-$count): "
select interface in "${free_interfaces[#]}"; do
DEFIF=$interface
break
done
echo "The interface $DEFIF will be used."
;;
esac

iterate over stdin fish (context: filter music files by genre grep)

I have this:
for file in **/*.ogg;
if ffprobe "$file" 2>&1 | sed -E -n 's/^ *GENRE *: (.*)/\1/p' | grep -q "$argv";
echo "$file"
else
end
end
but I would like to turn it into a function which will take a list of filenames as standard-input:
$ find . -maxdepth 1 -not -type d -exec du -h {} + | cut -f2 | filterByGenre Classical
You could do
function filterByGenre
while read line
do stuff with $line
end
end
or
function filterByGenre
set listOfLines (cat)
for line in $listOfLines
do stuff with $line
end
end

problems while reading log file with tail -n0 -F

i am monitoring the asterisk log file for peers that get offline.
the if part is working correct, but the sed command is not executed in the else part, although the echo command works. What do i need to change
tail -n0 -F /var/log/asterisk/messages | \
while read LINE
do
if echo "$LINE" | /bin/grep -q "is now UNREACHABLE!"
then
EXTEN=$(echo $LINE | /bin/grep -o -P "(?<=\').*(?=\')")
echo "$EXTEN is now UNREACHABLE!"
CALLERID=$(/bin/sed -n '/^\['"$EXTEN"'\]/,/^\[.*\]/{/^callerid*/p}' "$SIP" | /usr/bin/awk -F'=' '{ print $2 }')
if .......
then
.......
fi
elif echo "$LINE" | /bin/grep -q "is now REACHABLE!"
then
EXTEN=$(echo $LINE | /bin/grep -o -P "(?<=\').*(?=\')")
echo "$EXTEN is now REACHABLE!"
if /bin/grep -qi "^$EXTEN;" $OFFLINE; then
/bin/sed -i '/^$EXTEN;/d' $OFFLINE
fi
fi
done
You have a quoting problem - you've used single quotes when the string includes a shell variable:
if /bin/grep -qi "^$EXTEN;" $OFFLINE; then
/bin/sed -i '/^$EXTEN;/d' $OFFLINE
fi
Try using double quotes instead:
if /bin/grep -qi "^$EXTEN;" $OFFLINE; then
/bin/sed -i "/^$EXTEN;/d" $OFFLINE
fi

Is there a way to achieve the same in "gnu parallel" with less nested quoting?

Although this script works, I am not happy about the excess of nested quoting, which makes the script very fragile and difficult to modify.
The script consists basically of parallel followed by a filter test argument followed by command arguments.
#!/bin/sh
uhrzeit_0=$(date --rfc-3339=ns) ; uhrzeit="$uhrzeit_0 $(echo "$uhrzeit_0" | sha512sum)" ;
find ./* -maxdepth 30 -type f -print0 | parallel --null \
"mimetype --output-format %m {} | grep video > /dev/null \
&& echo -en '\nSeparator: ' && echo -e $uhrzeit \
&& echo -n 'md5sum: ' && md5sum {} && echo -n 'du -h: ' \
&& du -h {} && ffmpeg -loglevel quiet -i {} -f ffmetadata - " > Film_metadata.txt
#!/bin/bash
uhrzeit_0=$(date --rfc-3339=ns)
uhrzeit="$uhrzeit_0 $(echo "$uhrzeit_0" | sha512sum)"
doit() {
F="$1"
mimetype --output-format %m "$F" | grep video > /dev/null &&
echo -en '\nSeparator: ' &&
echo -e $uhrzeit &&
echo -n 'md5sum: ' &&
md5sum "$F" &&
echo -n 'du -h: ' &&
du -h "$F" &&
ffmpeg -loglevel quiet -i "$F" -f ffmetadata -
}
export -f doit
find ./* -maxdepth 30 -type f -print0 |
parallel --null doit > Film_metadata.txt

Pattern extraction using SED or AWK

How do I extract 68 from v1+r0.68?
Using awk, returns everything after the last '.'
echo "v1+r0.68" | awk -F. '{print $NF}'
Using sed to get the number after the last dot:
echo 'v1+r0.68' | sed 's/.*[.]\([0-9][0-9]*\)$/\1/'
grep is good at extracting things:
kent$ echo " v1+r0.68"|grep -oE "[0-9]+$"
68
Match the digit string before the end of the line using grep:
$ echo 'v1+r0.68' | grep -Eo '[0-9]+$'
68
Or match any digits after a .
$ echo 'v1+r0.68' | grep -Po '(?<=\.)\d+'
68
Print everything after the . with awk:
echo "v1+r0.68" | awk -F. '{print $NF}'
68
Substitute everything before the . with sed:
echo "v1+r0.68" | sed 's/.*\.//'
68
type man grep
and you will see
...
-o, --only-matching
Show only the part of a matching line that matches PATTERN.
then type echo 'v1+r0.68' | grep -o '68'
if you want it any where special do:
echo 'v1+r0.68' | grep -o '68' > anyWhereSpecial.file_ending