LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Can Diff take arrays as input? (https://www.linuxquestions.org/questions/programming-9/can-diff-take-arrays-as-input-815191/)

NirvanaII 06-19-2010 05:52 PM

Can Diff take arrays as input?
 
Does diff not like arrays? How do achieve the following?

Code:

stuart@stuart:~/music transfer$ diff file1.txt file2.txt
1c1
< bonkers_in_phoenix.mp3
---
> bonker's_in_phoenix.mp3

But look:

Code:

stuart@stuart:~/music transfer$ echo $x
2
stuart@stuart:~/music transfer$ echo ${file[x]}
bonker's_in_phoenix.mp3
stuart@stuart:~/music transfer$ echo ${nopunc[x]}
bonkers_in_phoenix.mp3
stuart@stuart:~/music transfer$ diff ${file[x]} ${nopunc[x]}
stuart@stuart:~/music transfer$


makyo 06-19-2010 11:19 PM

Hi.

Some shells allow process substitution where the result of a command is substituted for a file:
Code:

#!/usr/bin/env bash

# @(#) s1        Demonstrate process substitution.

# Uncomment to run script as external user.
# export PATH="/usr/local/bin:/usr/bin:/bin"
# Infrastructure details, environment, commands for forum posts.
set +o nounset
pe() { for i;do printf "%s" "$i";done; printf "\n"; }
pl() { pe;pe "-----" ;pe "$*"; }
LC_ALL=C ; LANG=C ; export LC_ALL LANG
pe ; pe "Environment: LC_ALL = $LC_ALL, LANG = $LANG"
pe "(Versions displayed with local utility \"version\")"
c=$( ps | grep $$ | awk '{print $NF}' )
version >/dev/null 2>&1 && s=$(_eat $0 $1) || s=""
[ "$c" = "$s" ] && p="$s" || p="$c"
version >/dev/null 2>&1 && version "=o" $p diff
set -o nounset

# Define content of 2 arrays.

a=( now is the time )
b=( this is not then )

j=2
pl " Content of array element $j:"
pe ${a[$j]}
pe ${b[$j]}

pl " Results:"
diff <( echo ${a[$j]} ) <( echo ${b[$j]} )

exit 0

producing:
Code:

% ./s1

Environment: LC_ALL = C, LANG = C
(Versions displayed with local utility "version")
OS, ker|rel, machine: Linux, 2.6.26-2-amd64, x86_64
Distribution        : Debian GNU/Linux 5.0
GNU bash 3.2.39
diff (GNU diffutils) 2.8.1

-----
 Content of array element 2:
the
not

-----
 Results:
1c1
< the
---
> not

This is a property of the shell, not diff ... cheers, makyo

NirvanaII 06-20-2010 03:12 PM

Thanks makyo!

My knowledge is too limited to understand everything that is going on here, but I've got the 'bit I wanted' to work on my script. I'll read this again at some stage, once i've a deeper understanding of things.

Here's another problem that's driving me mad:

Code:

awk NR==$x Musiclist.txt | cut -d/ -f$num | basename $1 .mp3
How do I get the piped output to read as an argument for the basename command? I know I can do it with xargs but i'm wanting to avoid this command as it throws a fit when fed punctuation.

smeezekitty 06-20-2010 07:50 PM

Quote:

Originally Posted by NirvanaII (Post 4009564)
Thanks makyo!

My knowledge is too limited to understand everything that is going on here, but I've got the 'bit I wanted' to work on my script. I'll read this again at some stage, once i've a deeper understanding of things.

Here's another problem that's driving me mad:

Code:

awk NR==$x Musiclist.txt | cut -d/ -f$num | basename $1 .mp3
How do I get the piped output to read as an argument for the basename command? I know I can do it with xargs but i'm wanting to avoid this command as it throws a fit when fed punctuation.

Code:

basename $(awk NR==$x Musiclist.txt | cut -d/ -f$num | basename $1 .mp3)
or
Code:

basename `awk NR==$x Musiclist.txt | cut -d/ -f$num | basename $1 .mp3`

grail 06-20-2010 08:29 PM

I would add to smeezekitty's reply and say it is probably a waste to pipe all of this when awk more than likely would do all the work.
Just a thought ;)

NirvanaII 06-20-2010 09:08 PM

I'll have to read up on awk, grail. (so much to learn! :))

Hmm... that code is giving me the same output as before:

Code:

stuart@stuart:~/music transfer$ echo $num
7
stuart@stuart:~/music transfer$ echo $x
1
stuart@stuart:~/music transfer$ basename $(awk NR==$x Musiclist.txt | cut -d/ -f$num | basename $1 .mp3)
.mp3
stuart@stuart:~/music transfer$ basename `awk NR==$x Musiclist.txt | cut -d/ -f$num | basename $1 .mp3`
.mp3
stuart@stuart:~/music transfer$ awk NR==$x Musiclist.txt | cut -d/ -f$num
Neil Young - Don't Let it Bring You Down.mp3


grail 06-21-2010 12:48 AM

Maybe you would supply a before and after picture so we can help?

ie. are the names of mp3 files the only thing in Musiclist.txt or is there a path as well?

i also presume the after is just the name of the song without extension?

NirvanaII 06-21-2010 05:27 AM

Quote:

Originally Posted by grail (Post 4009802)
Maybe you would supply a before and after picture so we can help?

ie. are the names of mp3 files the only thing in Musiclist.txt or is there a path as well?

i also presume the after is just the name of the song without extension?

In the above example we are looking at the seventh field, of the absolute path entry for track one:

Code:

stuart@stuart:~/music transfer$ cat Musiclist.txt
/mnt/sda1/Music/Neil Young/Live/Neil Young - Don't Let it Bring You Down.mp3
/mnt/sda1/Music/Neil Young/Live/Neil Young - A Day i'n the Life (live@Gla.mp3
/mnt/sda1/Music/Neil Young/Live/Neil Young - A Day in the Life (live@Gla.mp3
/mnt/sda1/Music/Neil Young/Live/Neil Young - Out On The Weekend.mp3
/mnt/sda1/Music/Neil Young/Live/Neil Young OLD MAN.mp3
/mnt/sda1/Music/Neil Young/Live/Neil Young - Needle and the Damage Done.mp3


grail 06-21-2010 06:43 AM

So I have 2 solutions you can choose from:

One liner:
Code:

awk -F"/" '{sub(/\..*/,"",$NF);print $NF}' Musiclist.txt
Short bash script:
Code:

#!/bin/bash

while read line
do
        tmp=$(basename "${line}" | cut -d. -f1)

        echo "$tmp"
done < Musiclist.txt

You could also change basename for parameter substitution, but either works ok :)

NirvanaII 06-21-2010 07:29 AM

Quote:

Originally Posted by grail (Post 4010043)
So I have 2 solutions you can choose from:

One liner:
Code:

awk -F"/" '{sub(/\..*/,"",$NF);print $NF}' Musiclist.txt
Short bash script:
Code:

#!/bin/bash

while read line
do
        tmp=$(basename "${line}" | cut -d. -f1)

        echo "$tmp"
done < Musiclist.txt

You could also change basename for parameter substitution, but either works ok :)

How would I go about combining the first of these commands with 'awk NR==$x Musiclist.txt'? i.e. Output line x of the list?

Why isn't smeezekitty's command working do you think?

(This awk command comes up with some frequency, i'm going to have to read into it as some point.)

grail 06-21-2010 07:36 AM

Cleanest way is probably:
Code:

awk -F"/" -v line=$x 'NR==line{sub(/\..*/,"",$NF);print $NF}' Musiclist.txt

NirvanaII 06-21-2010 07:41 AM

Quote:

Originally Posted by grail (Post 4010111)
Cleanest way is probably:
Code:

awk -F"/" -v line=$x 'NR==line{sub(/\..*/,"",$NF);print $NF}' Musiclist.txt

Nice work!

My program should work now, i'll test it all later today.

NirvanaII 06-21-2010 12:33 PM

If you're still interested grail, here's the close to finished command (it works, just crude!):

Code:

convert () { mplayer -cache 32 -ao pcm:file="${file[x]}".wav "${file[x]}".mp3; lame -V2 "${file[x]}".wav "${file[x]}".flac; } ; find "$My_Music" -iname "*.mp3" > Musiclist.txt ; y=$(sed 's@ @\\ @g' Musiclist.txt | wc -l); ((y=y+1));  typeset -i x; x=1; while ((x < y)) && fieldcut[x]=$(awk NR==$x Musiclist.txt | tr -d '[a-z,A-Z,0-9]',[' ','.','\55','\12','@','_','\50','\51','\47'] | wc -c) &&  path[x]=$(awk NR==$x Musiclist.txt | cut -d/ -f1-"${fieldcut[x]}") &&  file[x]=$(awk -F"/" -v line=$x 'NR==line{sub(/\..*/,"",$NF);print $NF}' Musiclist.txt) &&  ln -s "${path[x]}/${file[x]}".mp3 "${file[x]}".mp3; do ((x=x+1)); done ; x=1;  while (( x < y )) && convert; do (( x=x+1)); done;  rm -vf *.wav *.mp3 ; x=1; while (( x < 30)) && mv -v "${file[x]}".flac "${path[x]}"; do ((x=x+1)); done
I can see some bloat just looking at it:

Code:

fieldcut[x]=$(awk NR==$x Musiclist.txt | tr -d '[a-z,A-Z,0-9]',[' ','.','\55','\12','@','_','\50','\51','\47'] | wc -c) &&  path[x]=$(awk NR==$x Musiclist.txt | cut -d/ -f1-"${fieldcut[x]}")
$path[x] can be given in one awk command, i'm guessing, and fieldcut[x] purged.

Code:

y=$(sed 's@ @\\ @g' Musiclist.txt | wc -l); ((y=y+1))
And this expressed as one command. The 'sed command' was used for a different purpose originally, it just happens to work here.

The rest looks moderately trim to my unitiated eye. Now that it works -- to prune! Any suggestions, including instructions? :D

(and i'd still like to know what's up with smeezekitty's code???)

smeezekitty 06-21-2010 01:13 PM

Shell bug?
I use that method all the time and it works fine.

NirvanaII 06-21-2010 01:18 PM

Quote:

Originally Posted by smeezekitty (Post 4010538)
Shell bug?
I use that method all the time and it works fine.

I'm running the default shell in Antix (a Mepis fork), which I don't know, but would imagine is bash (?)

I'll boot up Puppy and try the command here...


All times are GMT -5. The time now is 01:28 PM.