I want to create a script that will use one of 4 id tags to search for the MP3 file on the drive. Up to this point i managed to create something like this, but it doesn't really work at all. Could someone suggest me what to fix?
#!/bin/bash
while getopts ":atbg:" opt; do
case $opt in
a) artist=${OPTARG}
;;
b) album=${OPTARG}
;;
t) title=${OPTARG}
;;
g) genre=${OPTARG}
;;
esac
done
find . -name '*.mp3' -print0 | while read -d $'\0' file
do
checkere=0
if [ "$album" != NULL ]
then
if [ !($(id3info "$file" | grep '$artist' sed -e 's/.*: //g')) ]
then
$checkere=1
fi
fi
if [ "$title" != NULL ]
then
if [ !($(id3info "$file" | grep '$title' sed -e 's/.*: //g')) ]
then
$checkere=1
fi
fi
if [ "$album" != NULL ]
then
if !($(id3info "$file" | grep '$album' sed -e 's/.*: //g'))
then
$checkere=1
fi
fi
if [ "$genre" != NULL ]
then
if !($(id3info "$file" | grep '$genre' sed -e 's/.*: //g'))
then
$checkere=1
fi
fi
if [ $checkere -eq 0 ]
then
echo $file
fi
done
#!/bin/bash
# Process command line args
while getopts a:b:t:g: arg ; do case $arg in
a) artist=${OPTARG} ;;
b) album=${OPTARG} ;;
t) title=${OPTARG} ;;
g) genre=${OPTARG} ;;
:) echo "${0##*/}: Must supply an argument to $OPTARG." ; exit 1 ;;
\?) echo "Invalid option. Abort" ; exit 1 ;;
esac
done
shift $(($OPTIND - 1))
[ "$#" -eq 0 ] || { echo "Incorrect usage" ; exit 1 ; }
# Find matching files
find . -name '*.mp3' -print0 |
while read -r -d $'\0' file
do
info=$(id3info $file)
[ "$artist" ] && { echo "$info" | grep -q "=== TPE1 (Lead performer(s)/Soloist(s)): $artist$" || continue ; }
[ "$album" ] && { echo "$info" | grep -q "=== TALB (Album/Movie/Show title): $album$" || continue ; }
[ "$title" ] && { echo "$info" | grep -q "=== TIT2 (Title/songname/content description): $title$" || continue ; }
[ "$genre" ] && { echo "$info" | grep -q "=== TCON (Content type): $genre$" || continue ; }
echo "$file"
done
Sample usage:
mp3search -a "The Rolling Stones" -t "Let It Bleed"
Related
#!/usr/bin/env zsh
doit() {
if [[ "$2" = "start" ]]; then
for loc in $(cat all-doc); do
if ! screen -list | grep -q My-$loc; then
screen -dmS My-$loc /home/Server -f /home/$loc.cfg
fi
done
elif [[ "$2" = "stop" ]]; then
for loc in $(cat all-doc); do
if screen -list | grep -q My-$loc; then
pkill -f My-$loc;
fi
done
else
echo "Option: ERROR..."
fi
}
nothing() {
if [[ "$2" = "start" ]]; then
echo "Option: 1"
elif [[ "$1" = "stop" ]]; then
echo "Option: 2"
else
echo "Option: 3"
fi
}
case "$2" in
start)
"$1" "$2";
;;
stop)
"$1" "$2";
;;
restart)
restart;
;;
*)
echo "Usage: $0 {doit|nothing} {start|stop|restart}"
exit 1
;;
esac
exit 0
I try to debug my script and this is the debug output with -x option.
Output:
./script.sh:33> case start (start)
./script.sh:35> doit start
doit:1> [[ '' = start ]]
doit:7> [[ '' = stop ]]
doit:14> echo 'Option: ERROR...'
Option: ERROR...
./script.sh:49> exit 0
I dont know why this happend but seems $2 get blank string [[ '' = start ]] and [[ '' = stop ]] im new in shell scripts and im try to do somthing for my game server, i got confuesed.
I finally grew tired of makefiles and wrote my own bash script to do my compiling. I wrote the whole thing, it works great, but for some reason, it freezes sometimes when I try to cancel it with ctrl-c. Here's the script:
#!/bin/bash
# Just to see if the script even sees the SIGINT
trap caught SIGINT
caught() { echo "hi"; }
compile() {
cpp=$(echo "$1" | sed -e 's/$/.cpp/' -e 's/^/src\//')
o=$(echo "$1" | sed -e 's/$/.o/' -e "s/^/$build_dir\//")
echo "$compile -c $cpp -o $o"
eval "$compile -c $cpp -o $o"
return $?
}
# I know this isn't normal, but I hate it when I forget to include something
# in the header and it fails way down the line
compile_h() {
h=$(echo "$1" | sed -e 's/$/.h/' -e 's/^/src\//')
o=$(echo "$1" | sed -e 's/$/.o/' -e "s/^/$build_dir\/headers\//")
echo "$compile -c $h -o /dev/null"
eval "$compile -x c++ -c $h -o $o"
if [ $? -ne 0 ]; then
return 1
fi
rm "$o"
return 0
}
build_type=$(awk 'NR==1' .build_options)
compile_command_debug=$(awk 'NR==2' .build_options)
link_command_debug=$(awk 'NR==3' .build_options)
compile_command_production=$(awk 'NR==4' .build_options)
link_command_production=$(awk 'NR==5' .build_options)
libraries=$(awk 'NR==6' .build_options)
# Make options for this build
build_dir="build"
compile="$compile_command_debug"
link="$link_command_debug"
if [ "$build_type" == "production" ]; then
build_dir="buildp"
compile="$compile_command_production"
link="$link_command_production"
fi
# These options need to be changeable later
output="game"
job_number=5
# There are more options, but they aren't important for this problem
while [ "$1" != "" ]; do
if [ "$1" == "clean" ]; then
rm -r $build_dir/*
fi
shift
done
# Get filenames
cpps=$(find src -name *.cpp | sed -e 's/src\///' -e 's/.cpp//' | sort)
hs=$(find src -name *.h | sed -e 's/src\///' -e 's/.h//' | sort)
# Ensure that all directories exist
directories=$(find src -type d | tail --lines=+2 | sed 's/src\///' | sort)
if [ ! -d "$build_dir/headers" ]; then
mkdir "$build_dir/headers"
fi
for dir in $directories; do
if [ ! -d "$build_dir/$dir" ]; then
mkdir "$build_dir/$dir"
fi
if [ ! -d "$build_dir/headers/$dir" ]; then
mkdir "$build_dir/headers/$dir"
fi
done
all_o="" # To be used for linking
# Determine what files need to be compiled
cpp_needed=""
h_needed=""
link_needed=false
# Check cpp files
for cpp_base in $cpps; do
o=$(echo "$cpp_base" | sed -e 's/$/.o/' -e "s/^/$build_dir\//")
all_o="$all_o $o"
d_file=$(echo "$cpp_base" | sed -e 's/$/.d/' -e "s/^/$build_dir\//")
if [ -f "$d_file" ]; then
d=$(<"$d_file")
d=$(echo "$d" | tr " " "\n" | tail --lines=+2 | grep "s")
if [ "$link_needed" = false ]; then
if [ "$o" -nt "$output" ]; then
link_needed=true
fi
fi
for dep in $d; do
if [ "$dep" -nt "$o" ]; then
if [ "$cpp_needed" == "" ]; then cpp_needed="$cpp_base"
else cpp_needed="$cpp_needed $cpp_base"
fi
link_needed=true
break
fi
done
else
if [ "$cpp_needed" == "" ]; then cpp_needed="$cpp_base"
else cpp_needed="$cpp_needed $cpp_base"
fi
link_needed=true
fi
done
# Check h files
for h_base in $hs; do
d_file=$(echo "$h_base" | sed -e 's/$/.d/' -e "s/^/$build_dir\/headers\//")
if [ -f "$d_file" ]; then
d=$(<"$d_file")
d=$(echo "$d" | tr " " "\n" | tail --lines=+2 | grep "s")
for dep in $d; do
if [ "$dep" -nt "$d_file" ]; then
if [ "$h_needed" == "" ]; then h_needed="$h_base"
else h_needed="$h_needed $h_base"
fi
break
fi
done
else
if [ "$h_needed" == "" ]; then h_needed="$h_base"
else h_needed="$h_needed $h_base"
fi
fi
done
# Compile
did_something=false
# Compile hs
while [ "$h_needed" != "" ]; do
for index in $(seq 1 $job_number); do
if [ "$h_needed" == "" ]; then break; fi
if ! kill -0 ${pids[index]} 2>/dev/null; then
new_file=$(echo "$h_needed" | awk '{print $1;}')
if [ $(echo "$h_needed" | wc -w) -eq 1 ]; then h_needed=""
else h_needed=$(echo "$h_needed" | cut -d " " -f2-)
fi
compile_h "$new_file" &
pids[index]=$!
did_something=true
fi
done
wait -n
if [ $? -ne 0 ]; then
wait
exit 1
fi
done
while [ $(pgrep -c -P$$) -gt 0 ]; do
wait -n
if [ $? -ne 0 ]; then
wait
exit 1
fi
done
# Compile cpps
while [ "$cpp_needed" != "" ]; do
for index in $(seq 1 $job_number); do
if [ "$cpp_needed" == "" ]; then break; fi
if ! kill -0 ${pids[index]} 2>/dev/null; then
new_file=$(echo "$cpp_needed" | awk '{print $1;}')
if [ $(echo "$cpp_needed" | wc -w) -eq 1 ]; then cpp_needed=""
else cpp_needed=$(echo "$cpp_needed" | cut -d " " -f2-)
fi
compile "$new_file" &
pids[index]=$!
did_something=true
fi
done
wait -n
if [ $? -ne 0 ]; then
wait
exit 1
fi
done
while [ $(pgrep -c -P$$) -gt 0 ]; do
wait -n
if [ $? -ne 0 ]; then
wait
exit 1
fi
done
# Compile program
if [ "$link_needed" = true ]; then
echo "$link $all_o -o game $libraries"
eval "$link $all_o -o game $libraries"
did_something=true
fi
# Make a message if nothing compiled
if [ "$did_something" = false ]; then
echo "Program is already compiled."
fi
It normally works perfectly. However, sometimes, when I try to cancel it with ctrl-c it just freezes. With a bit of debugging I saw that when the script wasn't setting up a new job, ctrl-c would work just fine. But when it was in the middle of setting up a new job, it would freeze the script. It wouldn't even catch the SIGINT (which that "echo hi" thing is for at the top). I honestly have no idea what's going on. Does anybody know what's going on? Thank you!
Edit: I realized I should probably mention I use g++ to compile.
Edit again: Here's an even-more stripped down version of the script. You would still need to setup some files to compile if you wanted to test it:
#!/bin/bash
# Just to see if the script even sees the SIGINT
trap caught SIGINT
caught() { echo "hi"; }
# I know this isn't normal, but I hate it when I forget to include something
# in the header and it fails way down the line
compile_h() {
h=$(echo "$1" | sed -e 's/$/.h/' -e 's/^/src\//')
o=$(echo "$1" | sed -e 's/$/.o/' -e "s/^/$build_dir\/headers\//")
echo "$compile -c $h -o /dev/null"
eval "$compile -x c++ -c $h -o $o"
if [ $? -ne 0 ]; then
return 1
fi
rm "$o"
return 0
}
build_type="debug"
build_dir="build"
compile="g++"
job_number=5
# Get filenames
hs=$(find src -name *.h | sed -e 's/src\///' -e 's/.h//' | sort)
h_needed=$(echo $hs)
# Compile hs
while [ "$h_needed" != "" ]; do
for index in $(seq 1 $job_number); do
if [ "$h_needed" == "" ]; then break; fi
if ! kill -0 ${pids[index]} 2>/dev/null; then
new_file=$(echo "$h_needed" | awk '{print $1;}')
if [ $(echo "$h_needed" | wc -w) -eq 1 ]; then h_needed=""
else h_needed=$(echo "$h_needed" | cut -d " " -f2-)
fi
compile_h "$new_file" &
pids[index]=$!
did_something=true
fi
done
wait -n
if [ $? -ne 0 ]; then
wait
exit 1
fi
done
while [ $(pgrep -c -P$$) -gt 0 ]; do
wait -n
if [ $? -ne 0 ]; then
wait
exit 1
fi
done
Any program that you run in your script may override your trap and set up its own. That trap might for example crash the currently running program for some reason. When this happens, take a look at the process tree in ps wafux to find the most likely culprit. For example, a zombie (Z) or uninterruptible sleep (D) process state (see man ps) is common when a process isn't going anywhere.
TABLE=`echo "${1}" | tr '[:upper:]' '[:lower:]'`
if [ $1 = -d ]
then TABLE=daminundation
elif [ $1 = -b ]
then TABLE=burnscararea
elif [ $1 = -r ]
then TABLE=riverpointinundation
elif [ $1 = " " ]
then echo "User must input -d (daminundation), -b (burnscararea)
or -r (riverpointinundation)."
fi
SHAPEFILEPATH=${2}
MERGEDFILENAME=${3}
if [ -z $3 ] ;
then MERGEDFILENAME=merged.shp
else
MERGEDFILENAME=${3}
fi
COLUMNNAME=${4}
if [ -n $4 ]
then COLUMNNAME=$4
fi
$3 & $4 are optional arguments. However, if I choose not to use $3 but I want to use $4, it will read the command as $3. Confused by other methods, how should I make it so that an undesired optional command can be bypassed for the next one?
You probably want this:
#!/bin/bash
while getopts ":b :d :r" opt; do
case $opt in
b)
TABLE=burnscararea
;;
d)
TABLE=daminundation
;;
r)
TABLE=riverpointinundation
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
esac
done
shift $((OPTIND-1))
[ -z "$TABLE" ] && ( echo "At least one of -b/-d/-r options must be provided"; exit 1; )
[ $# -ne 3 ] && ( echo "3 params expected!"; exit 1; )
SHAPEFILEPATH="$2"
MERGEDFILENAME="$3"
COLUMNNAME="$4"
# other stuff
I am having a problem with a unix shell script.
The script is for renaming the Files and directories which is having spaces with "-" recursively.
Example "Stack Overflow" to "Stack-Overflow"
This is running perfectly and working , But I get this wierd error which I don't know where it is coming.
I am getting the below error though (last line),
./script.sh[164]: [: Test.dat: unexpected operator/operand
I know it is coming some where in below funtions,
fix_dirs
fix_files
my_rename
but not sure where.
Could some one please help me in finding the error (Sorry for the long script :) )?.
#!/usr/bin/ksh
USAGE="$0 -f directory
$0 -d directory
$0 -d -f directory
-f rename files
-d rename directories
"
usage ()
{
print -u2 "$USAGE"
exit 1
}
pathname ()
{
print -- "${1%/*}"
}
basename ()
{
print -- "${1##*/}"
}
find_dirs ()
{
find "$1" -depth -type d -name '* *' -print
}
find_files ()
{
find "$1" -depth -type f -name '* *' -print
}
my_rename()
{
FROM_DIR="$1";
TO_DIR="$2";
if [ ! -w ${FROM_DIR##*/} ]
then
echo "Directory/file ${FROM_DIR##*/} Not Writable";
exit 1
fi
if [ -d "$TO_DIR" -o -f "TO_DIR" ]
then
echo "Target File or Directory already exists - $TO_DIR ";
exit 1
fi
mv "$FROM_DIR" "$TO_DIR"
STATUS=$?
if [ $STATUS -ne 0 ]
then
echo "Error in moving the file or directory";
echo "From directory : $FROM_DIR";
echo "To directory : $TO_DIR";
fi
}
fix_dirs ()
{
find_dirs "$1"|while read old_directory ; do
is_root_directory=`echo "old_directory" | grep -c "/"`;
if [[ $is_root_directory -ne 0 ]]
then
new_directory=$(pathname "$old_directory")/$(basename "$old_directory" | tr " " "_")
else
new_directory=$(echo "$old_directory" | tr " " "-")
fi
my_rename "${old_directory}" "${new_directory}"
done
}
fix_files ()
{
find_files "$1"|while read old_file ; do
new_file=$(pathname "$old_file")/$(basename "$old_file" | tr " " "-")
my_rename "${old_file}" "${new_file}"
done
}
WFILE=
WDIR=
DIR=
if [ "$#" -eq 0 ]
then
usage
fi
while [ $# -gt 0 ]
do
case $1 in
-d)
WDIR=1
;;
-f)
WFILE=1
;;
-*)
usage
;;
*)
if [ -d "$1" ]
then
DIR="$1"
else
print -u2 "$1 does not exist ..."
exit 1
fi
;;
esac
shift
done
if [ -z "$DIR" ]
then
echo "Please enter the directory";
exit 1
fi
if [ ${PWD} == "$DIR" ]
then
echo "Cannot perform rename on current directory";
exit 1
fi
if [ "$DIR" == "." -o "$DIR" == ".." ]
then
echo "cannot rename current or previous directory";
exit 1
fi
if [[ "$WDIR" == "" && "$WFILE" == "" ]] ; then
usage
exit 1
fi
if [ "$WDIR" -a "$WFILE" ]
then
fix_files "$DIR"
fix_dirs "$DIR"
elif [ "$WDIR" ]
then
fix_dirs "$DIR"
elif [ "$WFILE" ]
then
fix_files "$DIR"
fi
Running "ksh -n" on your example shows some possible problem on lines 70/71:
foo: warning: line 70: `...` obsolete, use $(...)
foo: warning: line 71: -ne within [[...]] obsolete, use ((...))
The relevant lines are
is_root_directory=`echo "old_directory" | grep -c "/"`;
if [[ $is_root_directory -ne 0 ]]
That was using a ksh93 on my Debian6, which likely is not the same version as the one you are using. However, you may find that making the suggested change to the second line will make your warning go away.
Thanks a lot for you information.
I tried bash similar to the ksh.
bash ./scriptname.sh
I corrected the errors. and below are the modified codes,
my_rename()
{
FROM_DIR="$1";
TO_DIR="$2";
if [ ! -w "${FROM_DIR##*/}" ]
then
echo "Directory/file ${FROM_DIR##*/} Not Writable";
exit 1
fi
if [ -d "$TO_DIR" -o -f "TO_DIR" ]
then
echo "Target File or Directory already exists - $TO_DIR ";
exit 1
fi
mv "$FROM_DIR" "$TO_DIR"
STATUS=$?
if [ $STATUS -ne 0 ]
then
echo "Error in moving the file or directory";
echo "From directory : $FROM_DIR";
echo "To directory : $TO_DIR";
fi
}
fix_dirs ()
{
find_dirs "$1"|while read old_directory ; do
is_root_directory=$(echo "$old_directory" | grep -c "/");
if [ $is_root_directory -ne 0 ]; then
new_directory=$(pathname "$old_directory")/$(basename "$old_directory" | tr " " "_")
else
new_directory=$(echo "$old_directory" | tr " " "-")
fi
my_rename "${old_directory}" "${new_directory}"
done
}
Thought this would have been more obvious, but I need to run a command whilst a key is being pressed, and stop the command (SIGINT) when it's no longer pressed.
For example:
#!/bin/bash
while [ F5 is being pressed ] ; do
arecord -f cd -t wav
done
Forwarding from PlayShell's keys.sh you can have:
#!/bin/bash
shopt -s extglob
KEYS_F5=$'\e[[E'
KEYS_XTERM_F5=$'\e[15~'
function keys_readonce {
__V0='' __V1=''
local A K
local -a KEY=() S=() T=()
for A; do
case "$A" in
+([[:digit:]]))
T=(-t "$A")
;;
-q|--quiet)
S=(-s)
;;
*)
echo "Invalid argument: $A"
exit 1
;;
esac
done
local IFS=''
if read -rn 1 -d '' "${T[#]}" "${S[#]}" K; then
KEY[0]=$K
if [[ $K == $'\e' ]]; then
if [[ BASH_VERSINFO -ge 4 ]]; then
T=(-t 0.05)
else
T=(-t 1)
fi
if read -rn 1 -d '' "${T[#]}" "${S[#]}" K; then
case "$K" in
\[)
KEY[1]=$K
local -i I=2
while
read -rn 1 -d '' "${T[#]}" "${S[#]}" "KEY[$I]" && \
[[ ${KEY[I]} != [[:upper:]~] ]]
do
(( ++I ))
done
;;
O)
KEY[1]=$K
read -rn 1 -d '' "${T[#]}" 'KEY[2]'
;;
[[:print:]]|$'\t'|$'\e')
KEY[1]=$K
;;
*)
__V1=$K
;;
esac
fi
fi
__V0="${KEY[*]}"
return 0
fi
return 1
}
while keys_readonce 5 && [[ $__V0 == "$KEYS_F5" || $__V0 == "$KEYS_XTERM_F5" ]]; do ## 5 secs. timeout is optional
# Do something
:
done