I am writing a script which you can pass a file name into as an argument and it'll only run if it's a certain file extension.
flac2mp3 "01 Song.flac"
or
flac2mp3 "01 Song.FLAC"
I know there a lot of scripts out there showing you how to convert flac to mp3, but this is my script and I want to learn how to write the script using this method.
It's so I can learn arguments and for when I feel like converting only 1 individual file. (for multiple files I just wrote a for loop with *.flac inside the script)
I just want to learn how to check if the $1 argument contains *.[Ff][Ll][Aa][Cc]
Here's what I cobbled up together from the internet so far (which I know is embarrassingly wrong but I wanted to show what I was going for) :
#!/bin/bash
#flac2mp3
if [ -z $1 ] && [[$1 !=~ *.[Ff][Ll][Aa][Cc]]];then echo "Give FLAC File Name"; exit 0;fi
OUTF=${1%.flac}.mp3
ARTIST=$(metaflac "$1" --show-tag=ARTIST | sed s/.*=//g)
TITLE=$(metaflac "$1" --show-tag=TITLE | sed s/.*=//g)
ALBUM=$(metaflac "$1" --show-tag=ALBUM | sed s/.*=//g)
GENRE=$(metaflac "$1" --show-tag=GENRE | sed s/.*=//g)
TRACKNUMBER=$(metaflac "$1" --show-tag=TRACKNUMBER | sed s/.*=//g)
DATE=$(metaflac "$1" --show-tag=DATE | sed s/.*=//g)
flac -c -d "$1" | lame -m j -q 0 --vbr-new -V 0 -s 44.1 - "$OUTF"
id3 -t "$TITLE" -T "${TRACKNUMBER:-0}" -a "$ARTIST" -A "$ALBUM" -y "$DATE" -g "${GENRE:-12}" "$OUTF"
done
Please and Thank Your for the help.
Try the following code:
shopt -s nocasematch
if [[ $1 == *flac ]]; then
echo "ok"
fi
This is case insensitive.
EDIT
$ LANG=C help shopt
shopt: shopt [-pqsu] [-o] [optname ...]
Set and unset shell options.
Change the setting of each shell option OPTNAME. Without any option
arguments, list all shell options with an indication of whether or not each
is set.
Options:
-o restrict OPTNAMEs to those defined for use with `set -o'
-p print each shell option with an indication of its status
-q suppress output
-s enable (set) each OPTNAME
-u disable (unset) each OPTNAME
Exit Status:
Returns success if OPTNAME is enabled; fails if an invalid option is
given or OPTNAME is disabled.
If you run shopt alone in a shell, you will see al options available :
$ shopt
autocd on
cdable_vars on
cdspell off
checkhash off
checkjobs off
checkwinsize off
cmdhist on
compat31 off
compat32 off
compat40 off
compat41 off
direxpand off
dirspell off
dotglob on
execfail off
expand_aliases on
extdebug off
extglob on
extquote on
failglob off
force_fignore on
globstar on
gnu_errfmt off
histappend on
histreedit off
histverify off
hostcomplete off
huponexit off
interactive_comments on
lastpipe off
lithist off
login_shell off
mailwarn off
no_empty_cmd_completion off
nocaseglob off
nocasematch off
nullglob off
progcomp on
promptvars on
restricted_shell off
shift_verbose off
sourcepath on
xpg_echo off
To know what does all these options :
man bash | less +/'^SHELL BUILTIN COMMANDS'
then search `shopt from within this section.
Related
set allows tweaking shell execution, by enabling some features. Some of the most popular are:
set -e # exit on error
set -x # print executed commands
Is there a way within a script to detect currently enabled features?
In my particular case I would like to know if the set -x was called.
Use the $- variable:
$ echo $-
himBCHs
$ set -e
$ set -x
$ echo $-
ehimxBCHs
^ ^
So:
if [[ $- == *x* ]]; then
echo "xtrace is set"
fi
The command set -o prints all the configured bash options.
The builtin shopt can probably show what you wanted.
In man bash
errexit Same as -e
Now
help shopt
Output
shopt: shopt [-pqsu] [-o] [optname ...]
Set and unset shell options.
Change the setting of each shell option OPTNAME. Without any option
arguments, list each supplied OPTNAME, or all shell options if no
OPTNAMEs are given, with an indication of whether or not each is set.
Options:
-o restrict OPTNAMEs to those defined for use with `set -o'
-p print each shell option with an indication of its status
-q suppress output
-s enable (set) each OPTNAME
-u disable (unset) each OPTNAME
Exit Status:
Returns success if OPTNAME is enabled; fails if an invalid option is
given or OPTNAME is disabled.
shopt -qo errexit
echo $?
It returns 1 if disabled or 0 if enabled.
Now to have an actual test.
if shopt -qo errexit; then
printf 'errexit is enabled!\n'
fi
Or if you want to negate use the bang !
if ! shopt -qo errexit; then
printf 'errexit is disabled!\n'
fi
I've defined the variables here to shorten the logic a little. The wget works fine (downloads the correct file) and grepping for tar.gz works in the wget.log
The issue is the match to another file!
Basically, if it's on a blacklist I want it to skip!
var1=https://somewebsite.com/directory
line1=directory
sudo wget -O wget.log https://somewebsite.com/$line1/releases
if grep -q "tar.gz" wget.log | "$var1" -ne grep -q
"https://somewebsite.com/$line1" banned; then
echo "Good Job!"
else
echo "Skip!"
fi
Use && to test if both of the grep commands succeed
if grep -q -F 'tar.gz' wget.log && grep -q -F -x "$variable" banned
then
echo "Skip!"
else
echo "Good Job!"
fi
I've used the -F option to grep because none of the strings we're searching for are regular expressions, they're fixed strings. And I used -x in the second grep to match the whole line in the blacklist.
I made a simple shell script to process mp3 files with SoX.
for f in ./*.mp3; do sox "$f" "${f%%.mp3}S.mp3" silence 1 0.02 1% -1 0.02 1%; done
The syntax should be like this:
sox in.wav out.wav silence 1 0.1 1% -1 0.1 1%
It will remove silence from the files I have in a folder, and create a new file with an "X" at the end (to distinguish from the original). I saved the script in my /bin folder and it works fine.
However, now I want to use it with PPSS, in order to run 8 instances in parallel. I cannot seem to get it working though, in the log file the error I keep getting is this error in the logs:
/usr/local/bin/ppss: line 2283: soxy.sh/Users/marw/Downloads/testfolder//ppss_dir/job_log/_Users_marw_Downloads_testfolder__10_audio_mp3: No such file or directory
Status: FAILURE
Total processing time (hh:mm:ss): 00:00:01
The PPSS syntax should be like this:
|P|P|S|S| Distributed Parallel Processing Shell Script 2.97
usage: /usr/local/bin/ppss [[ -d <sourcedir> | -f <sourcefile> ]] [[ -c '<command> "$ITEM"' ]]
[[ -C <configfile> ]] [[ -j ]] [[ -l <logfile> ]] [[ -p <# jobs> ]]
[[ -q ]] [[ -D <delay> ]] [[ -h ]] [[ --help ]] [[ -r ]] [[ --daemon ]]
Examples:
/usr/local/bin/ppss -d /dir/with/some/files -c 'gzip '
/usr/local/bin/ppss -d /dir/with/some/files -c 'cp "$ITEM" /tmp' -p 2
/usr/local/bin/ppss -f <file> -c 'wget -q -P /destination/directory "$ITEM"' -p 10
I'm new to shell scripting, forgive me if it's a stupid question. My OS is MacOS 10.11.5.
This is what I'm trying with PPSS:
ppss -d /Users/marw/Downloads/testfolder -c 'soxy.sh'
Maybe I have to write the my original script differently? It works fine without PPSS though.
EDIT:
I got a debug log here: http://pastebin.com/wak47rf8
The -c argument has to have a trailing space at the end. This works:
ppss -d /Users/marw/Downloads/testfolder -c 'soxy.sh '
Whereas this does not work:
ppss -d /Users/marw/Downloads/testfolder -c 'soxy.sh'
I got this from the PPSS wiki on Github:
The -c option specifies the command that will be executed by PPSS in
parallel for each file within the directory specified by -d. In this
example the command has a trailing space, which is necessary since the
command will expand to 'gzip example.tar' when executed. If the space
is omitted, an error will occur.
I declare three variables.
$1=`ssh <server_1> cat /etc/passswd|cut -f -d:|grep -e $IID -e $EID`
$2=`ssh <server_2> cat /etc/shadow|cut -f -d:|grep -e $IID -e $EID`
$3=`ssh <server_3> cat /etc/passwd}|cut -f -d:|grep -i $CID`
The above three variables are created by taking ssh to servers and checking the presence of the IDs which I give as input. If the ID doesn't exist already, the the variable is going to be null.
Now, how do I verify if all the three variables are null. I wanted to use the OR condition specified within an IF.
I tried,
if [ -s "$1" -o -s "$2" -o -s "$3"];then
echo -$1 $2 $3 "already exist(s)"
It didnt work. Please advise.
PS: I have just begun my career in Unix and correct me If am wrong anywhere.
Several points.
When you assign to a variable, don't use the dollar sign:
foo=xxx
Variables $1, $2 etc are already used for your command line arguments. Pick other names. But not $4please. :-)
When you specify a command for ssh, and it has arguments, it has to be quoted, because the command needs to be a single argument for ssh. In your case use double quotes, as you want variable expansion for $IID etc.
Most Unix utils are able to open input files themselves, so you don't need to start your pipeline with cat.
foo=`ssh <server_1> "cut -f -d: /etc/passwd | grep -e $IID -e $EID"`
Or something like that.
It was a typo in my question. I had actually declared it as,
1=`ssh <server_1> cat /etc/passswd|cut -f -d:|grep -e $IID -e $EID`
2=`ssh <server_2> cat /etc/shadow|cut -f -d:|grep -e $IID -e $EID` and so on.
And I tried it as ,
if [ -s "$1" -o -s "$2" -o -s "$3"];then
echo -e $1 $2 $3 "already exist(s)"
Since I had to Deliver my script today, I used the conventional method of,
ssh <server_1> "cat /etc/passswd|cut -f -d:|grep -e $IID -e $EID" > file1
ssh <server_2> "cat /etc/shadow|cut -f -d:|grep -e $IID -e $EID" > file2
ssh <server_3> "cat /etc/passwd|cut -f -d:|grep -ix $CID" > file3
if [ -s file1 -o -s file2 -o -s file3]; then
for i in `cat file1 file2 file3`
do
echo $i "already exists"
done
else
And I have now learnt from my first post, that -s to ensure that a file is not empty and -z is to ensure string is empty.
I was writing a small script to mass upload videos to youtube.. It looks like this:
#! /bin/sh
python --version
for file in ./*.mp4 ; do
export title=$(basename "$file" ".mp4")
echo $title "for" $file
youtube-upload -m mail#mailer.com -p pass -c Category -t "$title" -d "description" "$file"
done
Where youtube-upload is a cli based python uploader..
My question is as you can see i'm taking the title from the file name path, and the description is always the same :(. I want to write the description into a text or xml file parse it, and then upload with a proper description for each file..
How to do this using shell commands in this context?
Thanks for your suggestions
Have one file containing all of your filename->description mappings:
my file.mp4 this is a description
file2.mp4 this is another description
my last file.mp4 this is a description
ilied.mp4 description
And then just grab the line beginning with the filename and use the rest of the line:
#! /bin/sh
python --version
for file in ./*.mp4 ; do
export title=$(basename "$file" ".mp4")
echo $title "for" $file
youtube-upload -m mail#mailer.com -p pass -c Category -t "$title" -d "$(grep "^$(basename "$file")" desc | sed 's/.*.mp4 //')" "$file"
done
Looking at what's in the $(...):
grep "^$(basename "$file")" desc | sed 's/.*.mp4 //'
The grep finds the line that starts with the basename($file) in the "desc" file and then uses sed to get rid of the filename, leaving the rest of the line (which would be the description).
Note that this doesn't need to be a part of the youtube-upload comand line. You can also toss it into a variable:
#! /bin/sh
python --version
for file in ./*.mp4 ; do
export title=$(basename "$file" ".mp4")
echo $title "for" $file
description=$(grep "^$(basename "$file")" desc | sed 's/.*.mp4 //')
youtube-upload -m mail#mailer.com -p pass -c Category -t "$title" -d "$description" "$file"
done