Use cat to combine mp3 files based on filename - bash

I have a large number of downloaded radio programs that consist of 4 mp3 files each. The files are named like so:
Show Name - Nov 28 2011 - Hour 1.mp3
Show Name - Nov 28 2011 - Hour 2.mp3
Show Name - Nov 28 2011 - Hour 3.mp3
Show Name - Nov 28 2011 - Hour 4.mp3
Show Name - Nov 29 2011 - Hour 1.mp3
Show Name - Nov 29 2011 - Hour 2.mp3
Show Name - Nov 29 2011 - Hour 3.mp3
Show Name - Nov 29 2011 - Hour 4.mp3
Show Name - Nov 30 2011 - Hour 1.mp3 and so on...
I have used the cat command to join the files with great success by moving the four files of the same date into a folder and using the wildcard:
cat *.mp3 > example.mp3
The files are all the same bitrate, sampling rate, etc.
What I would like to do is run a script that will look at the file name and combine hours 1-4 of each date and name the file accordingly. Just the show name, the date and drop the 'Hour 1'.
I looked around and found a number of scripts that can be used to move files around based on their names but I'm not adept enough at bash scripting to be able to understand the methods used and adapt them to my needs.
I'm using Ubuntu 14.04.
Many thanks in advance

You can use a bash for loop to find each distinct date name and then construct the expected mp3 names from that.
Because your files have spaces in their names and my solution uses globbing, you'll also have to edit your Internal Field Separator to ignore spaces for the duration of the script.
SAVEIFS=$IFS
IFS=$'\n\b'
for mdy in `/bin/ls *mp3 | cut -d' ' -f'4,5,6' | sort -u`; do
cat *${mdy}*.mp3 > "showName_${mdy}_full.mp3"
done
IFS=$SAVEIFS
This won't alert you if some hours are missing for some particular date. It'll just join together whatever's there for that date.
Note: The comment pointing out that cat probably won't work for these files is spot on. The resulting file will probably be corrupted. You probably want to use something like mencoder or ffmpeg instead. (Check out this thread.)

Related

How to enforce bash to recognize letters case in files names in MacOS bash?

I bumped into the fact that MacOS GNU bash5.1.16 "ls" command doesn't differentiate between lower and upper case in the files names ( weird, I know)
e.g.
[17:39:28:~/Work/cloud-formation/output/templates$] ls -l Man*
-rw-r--r-- 1 geoku staff 71244 31 Jan 17:23 ManagementProd.json
-rw-r--r-- 1 geoku staff 67569 31 Jan 17:23 ManagementStage.json
Now, I can get the exactly same file listed with a different command:
[17:44:19:~/Work/cloud-formation/output/templates$] cksum ManagementStage.json Managementstage.JsOn
cksum ManagementStage.json Managementstage.JsOn
3327010753 67569 ManagementStage.json
3327010753 67569 Managementstage.JsOn
Is it some sort of bash settings?
OK, it turns out MacOS disk partitions can be created case-sensitive or not, and default is apparently the second one
Disk utility shows the options when one is trying to create a new partition
enter image description here

Recursively searching a directory without changing directory atimes

I'm checking an alternative to 'find' command in shell scripting so as to eliminate the discrepancy of Accessed date of sub directories.
According to my observation, when find command is executed to list all the files in a directory, the accessed date of sub-directories is getting changed.
I want to post genuine statistics in one of the junk platforms, So I have been looking at some forums and got the alternative with 'ls' command. But that doesn't completely fulfill my request.
Below is the answer given by #ghostdog74.
ls -R %path% | awk '/:$/&&f{s=$0;f=0} /:$/&&!f{sub(/:$/,"");s=$0;f=1;next} NF&&f{ print s"/"$0 }'.
But this finds only the files inside the sub directories. I need all the files and sub-directories' files to be listed.
For example:
bash-3.2# pwd
/Users/manojkapalavai/Desktop/SleepTimeReport
bash-3.2# ls
**6th floor** manoj17 manoj26.txt manoj36 manoj45.txt manoj55 manoj70.txt manoj80 manoj9.txt **test1**
manoj14 manoj23.txt manoj33 manoj42.txt manoj52 manoj61.txt manoj71 manoj80.txt manoj90 **test2**.
The highlighted ones are sub-directories inside "SleepTimeReport" directory and remaining are just files. So, when I execute the above command, I get only the below output.
bash-3.2# ls -R ~/Desktop/SleepTimeReport | awk '/:$/&&f{s=$0;f=0} /:$/&&!f{sub(/:$/,"");s=$0;f=1;next} NF&&f{ print s"/"$0 }'.
~/Desktop/SleepTimeReport/6th floor/Script to increase the Sleep Time.numbers.
~/Desktop/SleepTimeReport/6th floor/Zone1Sleep.pages.
~/Desktop/SleepTimeReport/test1/New_folder.
~/Desktop/SleepTimeReport/test1/manoj.txt.
~/Desktop/SleepTimeReport/test1/sathish.txt.
~/Desktop/SleepTimeReport/test1/vara.txt.
~/Desktop/SleepTimeReport/test1/New_folder/Script to increase the Sleep Time.numbers.
~/Desktop/SleepTimeReport/test1/New_folder/Zone1Sleep.pages.
i.e.; only those files inside sub-directories are listed.
Brief explanation of what issue I'm facing, please see below
Manojs-MacBook-Pro:SleepTimeReport manojkapalavai$ ls -l
total 16
drwxr-xr-x 8 manojkapalavai staff 272 Sep 14 15:07 6th floor
-rwxr-xr-x 1 manojkapalavai staff 59 Nov 13 10:41 AltrFind.sh
-rw-r--r-- 1 manojkapalavai staff 0 Nov 2 15:15 manoj%.txt
-rw-r--r-- 1 manojkapalavai staff 0 Nov 2 18:23 manoj1
When I try finding Created time and Accessed Time of the folder 6th floor before using 'find' command, the below is output.
Manojs-MacBook-Pro:SleepTimeReport manojkapalavai$ stat -f '%N, %SB, %Sa' 6th\ floor/
6th floor/, Sep 13 10:34:55 2017, **Nov 13 11:21:33 2017**
Manojs-MacBook-Pro:SleepTimeReport manojkapalavai$ find /Users/manojkapalavai/Desktop/SleepTimeReport/
/Users/manojkapalavai/Desktop/SleepTimeReport/
/Users/manojkapalavai/Desktop/SleepTimeReport//6th floor
/Users/manojkapalavai/Desktop/SleepTimeReport//6th floor/.DS_Store
/Users/manojkapalavai/Desktop/SleepTimeReport//6th floor/Script to increase the Sleep Time.numbers
/Users/manojkapalavai/Desktop/SleepTimeReport//6th floor/Zone1Sleep.pages
Now, after finding all the files inside a directory, below is the output of atime. you can notice the change
Manojs-MacBook-Pro:SleepTimeReport manojkapalavai$ stat -f '%N, %SB, %Sa' 6th\ floor/
6th floor/, Sep 13 10:34:55 2017, **Nov 13 14:26:03 2017**
All tha I have done is just find the files, and atime of sub-folders inside a folder when we find is getting changed to that current time.
Is there any way to solve this?
ls is the wrong tool for programmatic use. Generally, you should be able to fix your find usage to not have an effect on atimes (actually, it's pretty rare for folks to even have atimes enabled at the filesystem level on modern production systems), but if you really want to avoid it, consider the bash globstar option:
shopt -s globstar
for file in **/*; do
echo "Doing whatever with $file"
done

Parse line for specific date format?

Writing a script using bash. I am trying to look through lines in a file for a specific date format:
date +"%a %b %d %T %Z %Y"
For example, if the line were
/foo/bar/foobar this 12 is 411 arbitrary stuff in the line Wed Jun 10 10:10:10 PST 2017
I would want to obtain Wed Jun 10 10:10:10 PST 2017.
Any way to search for specific date formats?
I'm not sure whether you'll agree with this approach. But if this is for some quick, non-recurring work, I won't look for a perfect solution that can handle all the scenarios.
To start with, you can use the following too generic pattern to match the part you want.
cat file | sed -n 's/.*\(... ... .. ..:..:.. ... ....\).*/\1/p'
Then you can enhance this further restricting the matches as you need.
E.g.
cat file | sed -n 's/.*\([a-Z]\{3\} [a-Z]\{3\} [0-3][0-9] [0-2][0-9]:[0-5][0-9]:[0-5][0-9] [A-Z]\{3\} [0-9]\{4\}\).*/\1/p'
Note that this still is not perfect and can match invalid contents. If you find it still not good enough, you can further fine tune the pattern to the point you want.

How to find the date using internet (ie ntp) from bash?

How can I learn date and time from the internet using bash without installing anything extra.
I am basically looking for an equivalent of bash $ date, but using an NTP (or any other way) to get the correct date and time from the internet. All the methods I find (such as ntpd) are meant to correct the system time, which is not my purpose.
date has a lot of options for formatting, but I'm assuming that you just want the date and time:
ntpdate -q time.google.com | sed -n 's/ ntpdate.*//p'
(or any other time server)
If you have ntpd installed & configured then you can use the NTP Query command ntpq -crv which will return;
associd=0 status=04ff leap_none, sync_uhf_radio, 15 events, stale_leapsecond_values,
version="ntpd 4.2.6p5#1.2349-o Mon Feb 6 07:22:46 UTC 2017 (1)",
processor="x86_64", system="Linux/4.10.13-1.el6.elrepo.x86_64", leap=00,
stratum=1, precision=-23, rootdelay=0.000, rootdisp=1.000, refid=PPS,
reftime=dd2c9f10.f25911ee Wed, Aug 2 2017 19:57:20.946,
clock=dd2c9f11.f4251b0a Wed, Aug 2 2017 19:57:21.953, peer=6516, tc=4,
mintc=3, offset=-0.005, frequency=-17.045, sys_jitter=0.110,
clk_jitter=0.007, clk_wander=0.003, tai=37, leapsec=201701010000,
expire=201706010000
You want the line starting clock which gives the time, date etc - you would be best parsing this out with awk or something if you just want the date stamp rather then everything else.
You do not need to be a root user to run the command. It won't set anything, but will query your local server (presuming your running ntp) and present the details.

Deriving URLs from date

I would like to automate a download of an image from a third party server with a CRON job and then upload the image to my website.
I have 2 issues:
First, the third party site changes the image name every day using the following logic:
http://thirdpartysite.com/ImageFinder.aspx?ReportID=FILENAME
where FILENAME is 26601 +14 for each day after 6 Oct 2014 (so 7 Oct would be 26615, 8 Oct would be 26629 etc).
How do I build this into a simple Linux bash script for use with wget?
Second, how do I upload this to my site via FTP (or similar) with the same script.
NOTE: I have permission to host the file on my site and have linked the original site / placed credit for the image.
Following the suggestions of #Abhay, first get the timestamp of Oct 6, let's store it in the variable $d0:
d0=$(date +%s -d 20141006)
Then store the timestamp of a target date, say Oct 8 and store it in $d1:
d1=$(date +%s -d 20141008)
Then you can calculate the difference and apply the required arithmetic operations in $((...)), like this:
echo $((26601 + 14 * (d1 - d0) / 60 / 60 / 24))
# outputs: 26629
The date command has one very good format: %s, which prints number of seconds since "epoch", which is the fixed date 1 January 1970, 00:00 UTC. I'll call it "timestamp". In combination with this, you can use the -d date-string, so that it prints the given date as number of seconds. Now you can take today's timestamp, subtract the timestamp of "6 Oct 2014" from it, and you get number of seconds between the two times. Now you can divide it by (60 * 60 * 24) to get it in number of days, and do further arithmetic to get the desired number, and make a file name out of it.
The date string formats that -d option takes are flexible, but as of now I am not sure whether it takes "6 Oct 2014" as is. Try a few permutations, or better, check the "info" page.

Resources