LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 11-02-2018, 08:59 AM   #1
BW-userx
LQ Guru
 
Registered: Sep 2013
Location: Somewhere in my head.
Distribution: Slackware (15 current), Slack15, Ubuntu studio, MX Linux, FreeBSD 13.1, WIn10
Posts: 10,342

Rep: Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242
Bash;awk:exiftool:pipping:arrays


I am trying to work out how to get all of the information off one just one pass of exiftool, instead of having to call exiftool for each 'field' of information I need.
like this:
Code:
    artist="$(exiftool -p '$Artist' "$FILE")"
    album="$(exiftool -p '$Album' "$FILE")"
    title="$(exiftool -p '$Title' "$FILE")"
    genre="$(exiftool -p '$Genre' "$FILE")"
I want to only make one pass on the file then extract all of the needed information and place it into its own variable to later use.


the problem is strings that contain spaces are counted as separate fields.

exiftool displays the range of information contained on a mp3 file, extracting only '/Title/ || /Artist/ || /Track/ || /Album/ || /Genre/ the out put can be something like this:
Code:
userx@slackOlatern:~/Music$ exiftool Areosmith-Last-Child.mp3 | awk '/Title/ || /Artist/ || /Track/ || /Album/ || /Genre/' 
Title                           : Last child
Artist                          : Aerosmith
Track                           : 14
Album                           : Classics live complete
Genre                           : Live
needing only what is on the right of the : (colon) there are spaces within the string for each which constitutes another field. I need to get each pattern, title, artist,track,album,genre etc into a separate variable for later use. Just the value and not anything else, being what is on the right side of the : (colon)

so for example Album value is 'Classics live complete' where that is 3 separate fields within one string. The string value is of course unknown, so the amount of fields needed for each separate string is an issue.

Code:
#!/bin/bash

working_dir=/home/userx/Music

script_dir=""$HOME"/scripts"

while read f ; 
do
	#put into an array
	fields=($(exiftool "$f" | awk '/Title/ || /Artist/ || /Track/ || /Album/ || /Genre/ {print $3,$4,$5,$6}'))
	echo $fields
	echo ${fields[@]}
	echo ${#fields[@]}
	echo
	 
	
	for i in ${!fields[@]}
	do
		echo ${fields[$i]}
	done


done <<<$(find "$working_dir" -type f -iname "*.mp3")
gives me this output
Code:
$ ./awkMP3
Last
Last child Aerosmith 14 Classics live complete Live
8

Last
child
Aerosmith
14
Classics
live
complete
Live
where giving the actual strings should be
Code:
Last child
Aerosmith
14
Classics live complete
Live
in respective variables
Code:
title="Last child"
artist="Aerosmith"
track="14"
album="Classics live complete"
genre="Live"
is the desired results,

I do not know what program to use, awk at the moment, to extract the output then place it into separate variables for later use.

Last edited by BW-userx; 11-02-2018 at 09:12 AM.
 
Old 11-02-2018, 09:14 AM   #2
l0f4r0
Member
 
Registered: Jul 2018
Location: Paris
Distribution: Debian
Posts: 900

Rep: Reputation: 290Reputation: 290Reputation: 290
Quote:
Originally Posted by BW-userx View Post
fields=($(exiftool "$f" | awk '/Title/ || /Artist/ || /Track/ || /Album/ || /Genre/ {print $3,$4,$5,$6}'))
Not tested but why don't you use a special field separator in awk (other than space) and distinguish values in your array accordingly?
For example, you could use awk OFS="|" and set IFS accoringly for your fields array. Of course, you need to choose something else than "|" if your fields can contain this character, so maybe you could take something exotic...
 
Old 11-02-2018, 09:21 AM   #3
BW-userx
LQ Guru
 
Registered: Sep 2013
Location: Somewhere in my head.
Distribution: Slackware (15 current), Slack15, Ubuntu studio, MX Linux, FreeBSD 13.1, WIn10
Posts: 10,342

Original Poster
Rep: Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242
Quote:
Originally Posted by l0f4r0 View Post
Not tested but why don't you use a special field separator in awk (other than space) and distinguish values in your array accordingly?
For example, you could use awk OFS="|" and set IFS accoringly for your fields array. Of course, you need to choose something else than "|" if your fields can contain this character, so maybe you could take something exotic...
awk is not my strong point, don't use it much, if ever. you wouldn't happen to know a good web page to use the ones I've looked at are too basic. or not the right search string to find what I am looking to do. I'll look up the OFS and IFS ..
 
Old 11-02-2018, 09:22 AM   #4
lougavulin
Member
 
Registered: Jul 2018
Distribution: Slackware,x86_64,current
Posts: 279

Rep: Reputation: 100Reputation: 100
As l0f4r0, and according this :
Code:
exiftool Areosmith-Last-Child.mp3 | awk '/Title/ || /Artist/ || /Track/ || /Album/ || /Genre/' 
Title                           : Last child
Artist                          : Aerosmith
Track                           : 14
Album                           : Classics live complete
Genre                           : Live
I'll do :
Code:
exiftool "$f" | awk -F ':' '/Title/ || /Artist/ || /Track/ || /Album/ || /Genre/ {print $2}'
 
1 members found this post helpful.
Old 11-02-2018, 09:30 AM   #5
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,907

Rep: Reputation: 7318Reputation: 7318Reputation: 7318Reputation: 7318Reputation: 7318Reputation: 7318Reputation: 7318Reputation: 7318Reputation: 7318Reputation: 7318Reputation: 7318
The "usual" way I think:
Code:
awk '
/Field1/ { f1=$2 }
/Field2/ { f2=$2 }
.....
/LastField/ { print f1 f2 f3 .... $2 }'
Obviously this should always be adjusted to the current file format and to the required output
 
Old 11-02-2018, 09:40 AM   #6
BW-userx
LQ Guru
 
Registered: Sep 2013
Location: Somewhere in my head.
Distribution: Slackware (15 current), Slack15, Ubuntu studio, MX Linux, FreeBSD 13.1, WIn10
Posts: 10,342

Original Poster
Rep: Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242
Quote:
Originally Posted by lougavulin View Post
As l0f4r0, and according this :
Code:
exiftool Areosmith-Last-Child.mp3 | awk '/Title/ || /Artist/ || /Track/ || /Album/ || /Genre/' 
Title                           : Last child
Artist                          : Aerosmith
Track                           : 14
Album                           : Classics live complete
Genre                           : Live
I'll do :
Code:
exiftool "$f" | awk -F ':' '/Title/ || /Artist/ || /Track/ || /Album/ || /Genre/ {print $2}'
I tried that print $2 without the -F ':' and haha all I needed was that -F part basically. that just does what I did in a different manner, I see and understand what you did, but it is then getting that into a separate variable for each complete string spaces and words together.

Last edited by BW-userx; 11-02-2018 at 10:22 AM.
 
Old 11-02-2018, 09:46 AM   #7
l0f4r0
Member
 
Registered: Jul 2018
Location: Paris
Distribution: Debian
Posts: 900

Rep: Reputation: 290Reputation: 290Reputation: 290
Quote:
Originally Posted by BW-userx View Post
awk is not my strong point, don't use it much, if ever. you wouldn't happen to know a good web page to use the ones I've looked at are too basic. or not the right search string to find what I am looking to do. I'll look up the OFS and IFS ..
I like https://docstore.mik.ua/orelly/unix3/sedawk/ch07_01.htm.
This is not a new resource but it's still valid for the most part and logic remains the same.
 
Old 11-02-2018, 09:59 AM   #8
BW-userx
LQ Guru
 
Registered: Sep 2013
Location: Somewhere in my head.
Distribution: Slackware (15 current), Slack15, Ubuntu studio, MX Linux, FreeBSD 13.1, WIn10
Posts: 10,342

Original Poster
Rep: Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242
OK it is now howto get them shoved into separate variables?
@lougavulin , this gives me
Code:
	exiftool "$f" | awk -F ':' '/Title/ || /Artist/ || /Track/ || /Album/ || /Genre/ {print $2}'

 Last child
 Aerosmith
 14
 Classics live complete
 Live
@pan64 , this gives me
Code:
exiftool "$f" | awk -F  ':'  '/Title/ { f1=$2 } /Artist/ {f2=$2 } /Track/ {f3=$2} /Album/ {f4=$2} /Genre/ {f5=$2}; 
	END {print f1 f2 f3 f4 f5}'
 Last child Aerosmith 14 Classics live complete Live
putting it into an array and I am back to where I started,
Code:
	fields=($(exiftool "$f" | awk -F  ':'  '/Title/ { f1=$2 } /Artist/ {f2=$2 } /Track/ {f3=$2} /Album/ {f4=$2} /Genre/ {f5=$2}; 
	END {print f1 f2 f3 f4 f5}'))
	
		
	for i in ${!fields[@]}
	do
		echo ${fields[$i]}
	done
Last
child
Aerosmith
14
Classics
live
so for each var or element if array is used

Code:
for i in ??
do

  field[$i]=??
done
I need to contain the string that has spaces within it as a whole , getting the information I got, as posted, it is the next step that I need, the getting it into another , separate variables is the issue.

Last edited by BW-userx; 11-02-2018 at 10:20 AM.
 
Old 11-02-2018, 10:13 AM   #9
michaelk
Moderator
 
Registered: Aug 2002
Posts: 25,730

Rep: Reputation: 5920Reputation: 5920Reputation: 5920Reputation: 5920Reputation: 5920Reputation: 5920Reputation: 5920Reputation: 5920Reputation: 5920Reputation: 5920Reputation: 5920
This might work. readarray is bash 4 command.

Code:
#array1[0]=Title, array1[1]=Artist and so on.
line=$(exiftool -p '$Title' -p '$Artist' file.mp3)
echo "$line"
readarray -t array1 <<< "$line"
echo "${array1[0]}"
For < bash 4 you can split a string into an array based on newline character too
Code:
IFS=$'\n' read -rd '' -a array1 <<<"$line"

Last edited by michaelk; 11-02-2018 at 10:24 AM. Reason: Update
 
1 members found this post helpful.
Old 11-02-2018, 10:27 AM   #10
lougavulin
Member
 
Registered: Jul 2018
Distribution: Slackware,x86_64,current
Posts: 279

Rep: Reputation: 100Reputation: 100
I didn't know readarray provided by michaelk, I should play with it.

But I would do something like this :
Code:
# Associative array
declare -A ARRAY
exiftool "$f" | awk -F ':' '/Title/ || /Artist/ || /Track/ || /Album/ || /Genre/ {gsub(/ *$/, "", $1); print $1 $2}' | while read META VALUE
do
  ARRAY[${META}]=${VALUE}

  echo "${META} = ${ARRAY[${META}]}"
done
 
Old 11-02-2018, 10:44 AM   #11
michaelk
Moderator
 
Registered: Aug 2002
Posts: 25,730

Rep: Reputation: 5920Reputation: 5920Reputation: 5920Reputation: 5920Reputation: 5920Reputation: 5920Reputation: 5920Reputation: 5920Reputation: 5920Reputation: 5920Reputation: 5920
I was also illustrating the fact that you can extract just the desired information straight from exiftool without needing awk.
 
1 members found this post helpful.
Old 11-02-2018, 10:45 AM   #12
BW-userx
LQ Guru
 
Registered: Sep 2013
Location: Somewhere in my head.
Distribution: Slackware (15 current), Slack15, Ubuntu studio, MX Linux, FreeBSD 13.1, WIn10
Posts: 10,342

Original Poster
Rep: Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242
Quote:
Originally Posted by michaelk View Post
This might work. readarray is bash 4 command.

Code:
#array1[0]=Title, array1[1]=Artist and so on.
line=$(exiftool -p '$Title' -p '$Artist' file.mp3)
echo "$line"
readarray -t array1 <<< "$line"
echo "${array1[0]}"
For < bash 4 you can split a string into an array based on newline character too
Code:
IFS=$'\n' read -rd '' -a array1 <<<"$line"
I'll give that a look see but what I am trying to mimic is this'
Code:
       # when assigning in the array a string with spaces as awk output has some strings with spaces, therefore
       #it is seen as a separate filed so it gets another $1 $2 etc... seperating the string prior to adding 
        # it to the array when it needs to be kept together as one string what has spaces in it like this


	go=("hello world" "go")
		
	for i in ${!go[@]}
	do
		echo ${go[$i]}
	done
	 
      hello world
      go

Last edited by BW-userx; 11-02-2018 at 10:53 AM.
 
Old 11-02-2018, 10:53 AM   #13
BW-userx
LQ Guru
 
Registered: Sep 2013
Location: Somewhere in my head.
Distribution: Slackware (15 current), Slack15, Ubuntu studio, MX Linux, FreeBSD 13.1, WIn10
Posts: 10,342

Original Poster
Rep: Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242
Quote:
Originally Posted by michaelk View Post
I was also illustrating the fact that you can extract just the desired information straight from exiftool without needing awk.
looking at yours it is just the same as I am already doing only putting it in an array.
Code:
  artist="$(exiftool -p '$Artist' "$FILE")"
    album="$(exiftool -p '$Album' "$FILE")"
    title="$(exiftool -p '$Title' "$FILE")"
    genre="$(exiftool -p '$Genre' "$FILE")"
having to be called for each type artist, title etc. where as exiftool gives everything on one pass, get that off the one pass , therefore eliminating having to keep calling exiftool for each one I need. for every one file it has to call exiftool 4 to 7 times depending on information needed before moving on to the next step in the process.

Last edited by BW-userx; 11-02-2018 at 10:56 AM.
 
Old 11-02-2018, 10:54 AM   #14
michaelk
Moderator
 
Registered: Aug 2002
Posts: 25,730

Rep: Reputation: 5920Reputation: 5920Reputation: 5920Reputation: 5920Reputation: 5920Reputation: 5920Reputation: 5920Reputation: 5920Reputation: 5920Reputation: 5920Reputation: 5920
At least with my version of exiftool -p '$Title' -p '$Artist' file.mp3 will put each extracted value on a new line and assigning it to a variable will be just one string including new lines. Your splitting the string on a new line character which should preserve spaces.

I am doing the same thing but as one command which is one pass as requested. I just didn't expand it.

Code:
line=$(exiftool -p '$Title' -p '$Artist' -p '$Album' -p '$Title' -p '$Genre' $FILE)

Last edited by michaelk; 11-02-2018 at 11:01 AM.
 
1 members found this post helpful.
Old 11-02-2018, 10:59 AM   #15
BW-userx
LQ Guru
 
Registered: Sep 2013
Location: Somewhere in my head.
Distribution: Slackware (15 current), Slack15, Ubuntu studio, MX Linux, FreeBSD 13.1, WIn10
Posts: 10,342

Original Poster
Rep: Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242Reputation: 2242
Quote:
Originally Posted by lougavulin View Post
I didn't know readarray provided by michaelk, I should play with it.

But I would do something like this :
Code:
# Associative array
declare -A ARRAY
exiftool "$f" | awk -F ':' '/Title/ || /Artist/ || /Track/ || /Album/ || /Genre/ {gsub(/ *$/, "", $1); print $1 $2}' | while read META VALUE
do
  ARRAY[${META}]=${VALUE}

  echo "${META} = ${ARRAY[${META}]}"
done
that looks like where my brain was starting to lean towards, so I can hopefully get $2 that in some are strings with spaces in them into the element as one element. let me work this on out and see what i get.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] while loop, bash arrays and multiline awk ambiguous redirect MensaWater Linux - Software 7 09-20-2017 09:18 AM
LXer: Master ExifTool Basics with Practical ExifTool LXer Syndicated Linux News 0 12-19-2014 02:43 AM
[SOLVED] Sort multiple colums using Awk Arrays Mr_Sherwood Programming 2 05-08-2012 02:17 PM
Question about arrays in awk takayama Programming 17 05-08-2011 02:09 PM
how to implement bidimensional arrays in awk? akitty Programming 3 11-18-2008 06:54 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 07:24 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration