Renaming ID3 tag in Bash script with eyeD3 - linux

I have the following script that finds any file with the .mp3 extension in the incoming directory and moves it to the complete directory - it works perfectly!
#!/bin/bash
find /usr/audio/incoming -name '*.mp3' -exec mv {} /usr/audio/complete \;
exit
Now, I've installed eyeD3 (http://eyed3.nicfit.net/index.html) and I'm attempting to rename the Title tag somewhere during this entire process before it gets moved to the complete directory.
I've tried the following (and many more) but none of them work at all:
Trying to do it all in the same line...
#!/bin/bash
find /usr/audio/incoming -name '*.mp3' eyeD3 -t "New Title" -exec mv {} /usr/audio/complete \;
exit
Trying to do it by splitting it up...
#!/bin/bash
cd /usr/audio/incoming eyeD3 -t "New Title" '*.mp3';
find /usr/audio/incoming -name '*.mp3' -exec mv {} /usr/audio/complete \;
exit
Even just trying to get eyeD3 to rename the tag and nothing else...
#!/bin/bash
cd /usr/audio/incoming eyeD3 -t "New Title" '*.mp3';
exit
I know that i'm doing something wrong, but I've searched high and low and there is virtually zero newbie support for eyeD3 that I can find. What there is out there tends to be for python scripts that don't really do what I need anyway.
Does anybody know where I'm going wrong here?
For clarity, I want to rename the tag of every single mp3 file in this directory with the same title, but all of the mp3s have different file names, which is why I'm using the wildcard instead of the file name. Maybe I'm doing this the wrong way?

I think this will work:
find /usr/audio/incoming -name '*.mp3' -exec eyeD3 -t 'New Title' '{}' \; -exec mv '{}' /usr/audio/complete \;

Related

Bash script to find .jpgs created within a certain time frame and then rename them

I have the following find command working pretty well which walks through a directory tree looking for any .jpg it finds with a file modification date of 600 minutes or less:
find /some/directory/ -depth -mmin -600 -name *.jpg
What I need to do now is rename all the .jpg it finds to the actual creation date that the .jpg was created on and create some random numbers at the end of the file before appending .jpg back to it. I've used this in the past: (date -r "$f" +%Y-%m-%d_%H-%M-%S-%N).jpg but I can't seem to figure out how to tie the find to the mv.
Am I missing a simple way to do this with -exec?
This should achieve what you wanted :
find /some/directory/ -depth -mmin -600 -name "*.jpg" \
-exec bash -c 'echo mv "$1" "$(dirname "$1")/$(date -r "$1" +%Y-%m-%d_%H-%M-%S-)$(date +%N).jpg"' bash {} \;
Remove echo to do renaming once you are satisfied with result.

Bash find- is showing the files but returning no such file or directory

I have a bash script I cannot get working. I am a dead set beginner in bash this is actually the first script I've ever used. I'm trying to get omxplayer to play a list of files in a directory. When the script runs I get feedback showing the file then the error that there is no such file or directory. Please help me?
#!/bin/sh
find /media/pi/88DC-E668/MP3/ -name "*.mp3" -exec PLAY={} \;; omxplayer "$PLAY";
This is the echo:
find: `PLAY=/media/pi/88DC-E668/MP3/Dance.mp3': No such file or directory
find: `PLAY=/media/pi/88DC-E668/MP3/Whitemary.mp3': No such file or directory
find: `PLAY=/media/pi/88DC-E668/MP3/Limo.mp3': No such file or directory
find: `PLAY=/media/pi/88DC-E668/MP3/Silo.mp3': No such file or directory
File "" not found.
Easy way:
find /media/pi/88DC-E668/MP3 -name \*.mp3 -exec omxplayer {} \;
or
while IFS= read -r -d '' mp3
do
omxplayer "$mp3"
done < <(find /media/pi/88DC-E668/MP3 -name \*.mp3 -print0)
or
find /media/pi/88DC-E668/MP3 -name \*.mp3 -print0 | xargs -0 -n1 omxplayer
You can omit the -n1 if the omxplayer could handle multiple filenames. In such case the 1st could be written as:
find /media/pi/88DC-E668/MP3 -name \*.mp3 -exec omxplayer {} +
but the simplest probably will be
#shopt -s globstar #the default is on
for mp3 in /media/pi/88DC-E668/MP3/{,**/}*.mp3
do
omxplayer "$mp3"
done
EDIT I stand corrected, but won't delete the answer as you can also learn from the mistakes of others. See comment and rather use this answer :)
So please don't do it like this, as this is a typical "happy path" solution - meaning: it works if you know what you're doing and you know your paths (e.g. that they don't contain spaces). I keep forgetting that many people don't know yet that spaces in paths are evil.
Just use xargs to pass what you found to your player like this:
#!/bin/sh
find /media/pi/88DC-E668/MP3/ -name "*.mp3" | xargs omxplayer
The -exec foo part means run the command foo for each path found.
In your case, -exec PATH={}, the {} part is replaced with the path name, ending up with something like -exec PATH=/media/pi/88DC-E668/MP3/Dance.mp3, and so then find tries to run the command PATH=/media/pi/88DC-E668/MP3/Dance.mp3 which fails because there isn't actually any such program to execute.
xargs is the usual way to do what you're trying to do, as described in another comment already.
You could also do:
find /media/pi/88DC-E668/MP3/ -name \*.mp3 |
while read f; do
omxplayer "$f"
done

Changing file extension within the file command

I am using the following command to find files, zip them up and delete the original file:
find data/* -type f -execdir zip '{}'.zip '{}' \; -delete
At the moment if a file called "something.txt" is found a zip file called "something.txt.zip" is created. How do I make the filename "something.zip" instead?
I know in bash I can do something like ${x:.*} but I cannot seem to get something like this working here.
This seems to work but it is a bit of a fudge:
find data/* -execdir bash -c 'zip -j "${1%.*}.zip" "${1}"' _ {} \;
I would love to see something cleaner.

Creating a file in a directory other than root using bash

I am currently working on an auto grading script for a class project. It has to be able to search any number of given directories lets say
for example
usr/autograder/jdoe/
jdoe contains two files house.c and readme.txt.
I need to create a file in jdoe called jdoe.pdf
Currently i'm using this line of code below to get the path to where i need to create the file. Where $1 is user input of the path containing the projects the auto grader will grade.
find $1 -name "*.txt" -exec sh -c "dirname {}"
When I try adding /somename.pdf to the end of this statement I get readme.txt/somename.pdf
along with another -exec to get the name for the file.
\; -exec sh -c "dirname {} xargs -n 1 basename" \;
I'm having problems combining these two into one working statement.
I'm new to unix programming and would appreciate any advice or help even if it means re-writing the code using different unix tools.
The main question here is how do I create files in a path other than the directory I call my script from. Thanks in advance.
How about this?
find "$1" -name "*.txt" -exec bash -c 'd=$(dirname "$1"); touch $d"/"$(basename "$d").pdf' - {} \;
You can create files in another path using change directory command (cd).
If you start your script in usr/autograder/script and want to change to usr/autograder/jdoe you can change directory with shell command cd ../jdoe (relative) or cd usr/autograder/jdoe (absolute).
Now you are in the directory of usr/autograder/jdoe and you are able to create files in this directory, for example gedit readme.txt will open gedit and creates the file in usr/autograder/jdoe.
The simplest way is to loop over the files returned by find and then do whatever you need to do.
For example:
find "$1" -type f -name "*.txt" -print0 | while IFS= read -r -d $'\0' filename; do
dir=$(dirname "$filename")
# create pdf file
touch "$dir/${dir##*/}.pdf"
done
(Note the use of find -print0 to correctly handle filenames containing whitespace and newline characters.)
Is this what you are looking for?
function process_file {
dir=$(dirname "$1")
name=$(basename "$1")
echo name is $name and dir is $dir;
cd "$dir"
touch "${dir##*/}.pdf" # or anything else
}
# export the function, so that it is known in the child processes
export -f process_file
find . -name '*.txt' -exec bash -c "process_file '{}'" \;

Renaming and moving wildcard files with Bash

I'm trying to do the following with this bash script but i've come unstuck..
1) Find every file with the extension .mp3 in the /usr/incoming/ directory
2) Use eyeD3 to strip all of the existing ID3 tags
3) Use eyeD3 to write a title tag "NEW NAME" back to the file
4) Use mv to rename every file with the extension .mp3 to latest.mp3 and then force move it (so it will overwrite any other file with the same name) to the usr/complete directory.
It's all working apart from the last bit (No.4).
I know i'm doing something wrong with the mv command but I'm not sure what.
Here's the code :
find /usr/incoming/ -name '*.mp3' \
-exec eyeD3 --remove-all -t 'NEW NAME' '{}' \; \
-exec mv -f '*.mp3' latest.mp3 /usr/complete \;
Can anybody show me the error of my ways? ;)
Change the *.mp3 in your later command to {} to pass in an explicit name of the file you just tagged. mv will refuse to rename multiple files to the same name in a single invocation -- when passed more than two arguments, it requires the last to be a directory -- and anyhow, anything given as an argument to find's -exec is passed as a literal argument, not through a shell, so globs aren't expanded, redirections aren't processed, etc. except for find's own special strings such as {}.
find /usr/incoming/ -name '*.mp3' \
-exec eyeD3 --remove-all -t 'NEW NAME' {} ';' \
-exec mv -f {} /usr/complete/latest.mp3 ';'

Resources