ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
The title is terrible, but essentially sums up what I need to do. I have a script that does the following:
Code:
cds into the home directory
finds all the videos in the vids directory
sorts them into order
removes the pathway and makes them more orderly
pipes them into dmenu for selection
passes the selected item to mpv
the UNIX shell script used is as follows:
Code:
cd ${HOME} && find vids/ -type f \( -name "*.mp4" -o -name "*.mkv" \) | sort | sed 's/.*\///' | pmenu -l 5 | xargs -I {} mpv "{}"
Now this works, sorta. This does display the output how I want, but once I select a video and it gets passed to mpv it can't play the video as the video doesn't exist. This is due to the fact that when the sed command gets run it changes the name of the file that mpv will try to play. I really want to change the name shown as it looks so much better and makes it easier to read, but how do I get mpv to play the original video?
Some sample output would be this:
Code:
#This is the vinilla output without using sed to parse output:
vids/Movies/Blade Runner 2049.mp4
vids/Movies/Blade Runner.mp4
vids/Movies/Ghost in the Shell (2017).mp4
vids/Movies/The God Who Wasnt There.mp4
vids/TV/Attack on Titan/S01E01 To You, Two Thousand Years Later.mkv
vids/TV/Attack on Titan/S01E02 That Day.mkv
vids/TV/Attack on Titan/S01E03 A Dull Light in Despair.mkv
vids/TV/Attack on Titan/S01E04 Night of the Disbanding.mkv
vids/TV/Attack on Titan/S01E05 First Battle.mkv
vids/TV/Attack on Titan/S01E06 The World She Saw.mkv
vids/TV/Attack on Titan/S01E07 A Small Blade.mkv
vids/TV/Attack on Titan/S01E08 I Can Hear a Heartbeat.mkv
vids/TV/Attack on Titan/S01E09 The Whereabouts of His Left Arm.mkv
vids/TV/Attack on Titan/S01E10 Answer.mkv
vids/TV/Attack on Titan/S01E11 Idol.mkv
vids/TV/Attack on Titan/S01E12 WOUND.mkv
vids/TV/Attack on Titan/S01E13 Basic Needs.mkv
vids/TV/Attack on Titan/S01E14 Can't Look into His Eyes.mkv
vids/TV/Attack on Titan/S01E15 Special Ops Squad.mkv
vids/TV/Attack on Titan/S01E16 What Should Be Done.mkv
vids/TV/Attack on Titan/S01E17 Female Titan.mkv
vids/TV/Attack on Titan/S01E18 Forest of Giant Trees.mkv
vids/TV/Attack on Titan/S01E19 Bite.mkv
vids/TV/Attack on Titan/S01E20 Erwin Smith.mkv
vids/TV/Attack on Titan/S01E21 Crushing Blow.mkv
vids/TV/Attack on Titan/S01E22 The Defeated.mkv
vids/TV/Attack on Titan/S01E23 Smile.mkv
vids/TV/Attack on Titan/S01E24 Mercy.mkv
vids/TV/Attack on Titan/S01E25 Wall.mkv
vids/TV/Death Note/S01EP01 Rebirth.mkv
vids/TV/Death Note/S01EP02 Confrontation.mkv
vids/TV/Death Note/S01EP03 Dealings.mkv
vids/TV/Death Note/S01EP04 Pursuit.mkv
vids/TV/Death Note/S01EP05 Tactics.mkv
vids/TV/Death Note/S01EP06 Unraveling.mkv
vids/TV/Death Note/S01EP07 Overcast.mkv
vids/TV/Death Note/S01EP08 Glare.mkv
vids/TV/Death Note/S01EP09 Encounter.mkv
vids/TV/Death Note/S01EP10 Doubt.mkv
vids/TV/Death Note/S01EP11 Assault.mkv
vids/TV/Death Note/S01EP12 Love.mkv
vids/TV/Death Note/S01EP13 Confession.mkv
vids/TV/Death Note/S01EP14 Friend.mkv
vids/TV/Death Note/S01EP15 Wager.mkv
vids/TV/Death Note/S01EP16 Decision.mkv
vids/TV/Death Note/S01EP17 Execution.mkv
vids/TV/Death Note/S01EP18 Ally.mkv
vids/TV/Death Note/S01EP19 Matsuda.mkv
vids/TV/Death Note/S01EP20 Makeshift.mkv
vids/TV/Death Note/S01EP21 Performance.mkv
vids/TV/Death Note/S01EP22 Guidance.mkv
vids/TV/Death Note/S01EP23 Frenzy.mkv
vids/TV/Death Note/S01EP24 Revival.mkv
vids/TV/Death Note/S01EP25 Silence.mkv
vids/TV/Death Note/S01EP26 Renewal.mkv
vids/TV/Death Note/S01EP27 Abduction.mkv
vids/TV/Death Note/S01EP28 Impatience.mkv
vids/TV/Death Note/S01EP29 Father.mkv
vids/TV/Death Note/S01EP30 Justice.mkv
vids/TV/Death Note/S01EP31 Transfer.mkv
vids/TV/Death Note/S01EP32 Selection.mkv
vids/TV/Death Note/S01EP33 Scorn.mkv
vids/TV/Death Note/S01EP34 Vigilance.mkv
vids/TV/Death Note/S01EP35 Malice.mkv
vids/TV/Death Note/S01EP36 1.28.mkv
vids/TV/Death Note/S01EP37 New World.mkv
# and with the parsing:
Blade Runner 2049.mp4
Blade Runner.mp4
Ghost in the Shell (2017).mp4
The God Who Wasnt There.mp4
S01E01 To You, Two Thousand Years Later.mkv
S01E02 That Day.mkv
S01E03 A Dull Light in Despair.mkv
S01E04 Night of the Disbanding.mkv
S01E05 First Battle.mkv
S01E06 The World She Saw.mkv
S01E07 A Small Blade.mkv
S01E08 I Can Hear a Heartbeat.mkv
S01E09 The Whereabouts of His Left Arm.mkv
S01E10 Answer.mkv
S01E11 Idol.mkv
S01E12 WOUND.mkv
S01E13 Basic Needs.mkv
S01E14 Can't Look into His Eyes.mkv
S01E15 Special Ops Squad.mkv
S01E16 What Should Be Done.mkv
S01E17 Female Titan.mkv
S01E18 Forest of Giant Trees.mkv
S01E19 Bite.mkv
S01E20 Erwin Smith.mkv
S01E21 Crushing Blow.mkv
S01E22 The Defeated.mkv
S01E23 Smile.mkv
S01E24 Mercy.mkv
S01E25 Wall.mkv
S01EP01 Rebirth.mkv
S01EP02 Confrontation.mkv
S01EP03 Dealings.mkv
S01EP04 Pursuit.mkv
S01EP05 Tactics.mkv
S01EP06 Unraveling.mkv
S01EP07 Overcast.mkv
S01EP08 Glare.mkv
S01EP09 Encounter.mkv
S01EP10 Doubt.mkv
S01EP11 Assault.mkv
S01EP12 Love.mkv
S01EP13 Confession.mkv
S01EP14 Friend.mkv
S01EP15 Wager.mkv
S01EP16 Decision.mkv
S01EP17 Execution.mkv
S01EP18 Ally.mkv
S01EP19 Matsuda.mkv
S01EP20 Makeshift.mkv
S01EP21 Performance.mkv
S01EP22 Guidance.mkv
S01EP23 Frenzy.mkv
S01EP24 Revival.mkv
S01EP25 Silence.mkv
S01EP26 Renewal.mkv
S01EP27 Abduction.mkv
S01EP28 Impatience.mkv
S01EP29 Father.mkv
S01EP30 Justice.mkv
S01EP31 Transfer.mkv
S01EP32 Selection.mkv
S01EP33 Scorn.mkv
S01EP34 Vigilance.mkv
S01EP35 Malice.mkv
S01EP36 1.28.mkv
S01EP37 New World.mkv
You can't do it like that with either pmenu or dmenu I think - they simply spit back out what you chose.
This would require some proper scripting, possibly with bash arrays, not a oneliner.
Have you tried simply using bash's tab completion feature on the command line?
between pmenu and xargs, add another find with '-name $(cat)', so find will give xargs file with full path
or replace last xargs with 'find vids -name "$(cat)" -exec mpv "{}" \;'
between pmenu and xargs, add another find with '-name $(cat)', so find will give xargs file with full path
or replace last xargs with 'find vids -name "$(cat)" -exec mpv "{}" \;'
I am very sorry, but could you give me a more detialed example? I am still learning the ins and outs of UNIX shell script and feel a little confused. To help myself with this I am breaking up the script like so
Code:
#!/bin/sh
cd ${HOME}
# find all videos
files=$(find vids/ -type f \( -name "*.mp4" -o -name "*.mkv" \))
# make titles easier to read
sorted=$("$files" | sort | sed 's/.*\///')
# select video to watch
chosen=$("$sorted" | pmenu -l 5 | xargs -I {} mpv "{}")
if I understand you correctly I am supposed to run:
Thank you, I'll keep this in my backpocket; but I want to do my best to do this with the tools I have at the moment.
Is it because you want to learn how "core utilities" work? Or is it because of "bloat?" There is a difference. Anyway, here is a POSIX-compliant version of the above, without the easy selection.
Code:
#!/bin/sh
cd "$HOME" || exit
find vids -type f -print | sed 's|.*/||'
read -p '> ' -r chosen
find vids -name "*$chosen" -exec mpv \{} \;
Is it because you want to learn how "core utilities" work? Or is it because of "bloat?" There is a difference. Anyway, here is a POSIX-compliant version of the above, without the easy selection.
Code:
#!/bin/sh
cd "$HOME" || exit
find vids -type f -print | sed 's|.*/||'
read -p '> ' -r chosen
find vids -name "*$chosen" -exec mpv \{} \;
#!/bin/sh
cd "$HOME" || exit
find vids -type f -print | sed 's|.*/||'
read -p '> ' -r chosen
find vids -name "*$chosen" -exec mpv \{} \;
IDK, I find this very... inelegant. and error perone, too: what if 2 videos are in different folders, but have the same name? And mpv does not seem to take a list of files by default.
Not that I could think of a better solution; the whole premise is faulty IMO.
IDK, I find this very... inelegant. and error perone, too: what if 2 videos are in different folders, but have the same name? And mpv does not seem to take a list of files by default.
Not that I could think of a better solution; the whole premise is faulty IMO.
Normally I would agree, but that wasn't the purpose of my post. It provided a starting point for the OP, and if he wants to expand, then more power to him. The directory/file structure is quite specific in this case so the likelihood of duplicate show/movie titles is low.
I actually have one other thing I am trying to figure out if you have a moment, this is something I will actually be implementing in several scripts. As you know this script will find all videos in the vids directory. The way I order my directories is:
Code:
vids/TV/"show names"/"seasons if any is available"
vids/Movies/"name of movies"
Now the thing I want to add is that I want the output (IE when I select my video) to show sections, like show all tv shows under "TV/show name/season if any is there" and movies as "Movies/moviename". A better way to display this would be with an example, so a better visual would be this:
Code:
TV:
Death Note:
Season one:
S01EP01 Rebirth.mkv
ETC
Movies:
Blade Runner 2049.mp4
Blade Runner.mp4
ETC
I have no idea how to do this, what would be the best way to do this? I want to get this working here as I plan to use it in a similar script for music. Just for clarification this would mean that the show for example is stored under ~/vids/Death Note/Season One/EP Name
So basically you want to split paths along '/' characters?
bash has some nice tools for that, specifically string manipulation: https://mywiki.wooledge.org/BashFAQ/100 (you really want to read ALL of the BashFAQ)
Example:
Code:
#!/bin/bash
path="/home/ondoho/video/CSI Crime Scene Investigation/CSI - 3x23 - Inside The Box.avi"
lastbit="${path##*/}"
echo "$lastbit"
beforelast="${path%/$lastbit}"
beforelast="${beforelast##*/}"
echo "$beforelast"
# etc...
I'm not sure I completely understood your question. You want to print out all files that are in the same directory as the selected one? If that's what you want you can add a few lines to what you already have.
Code:
# list all files in the vids directory and allow a user to choose one.
mediaFile="$(find vids -type f -print | sed 's|.*/||' | sort | pmenu -l 5)"
# find the directory that the chosen file resides in.
mediaDir="$(find vids -iname "*$mediaFile*" -exec dirname \{} \; -quit)"
# remove vids/ from the front of the directory name; replace / with a newline; replace the end of each resulting string with ':.'
echo "$mediaDir" | cut -d'/' -f2- | tr '/' '\n' | sed 's|$|:|'
# list the contents of the directory.
ls -1 "$mediaDir"
# start mpv with $mediaFile here?
And the result:
Code:
TV:
Death Note:
Season One:
S01EP01 Rebirth.mkv
S01EP02 Confrontation.mkv
EDIT: I learned something new as well. You can stop find after the first match by using -quit.
Last edited by individual; 06-28-2019 at 03:20 AM.
Reason: Typo
I am gonna rewrite this to make it easier to read (sorry about the last one, it was poorly formatted). What I am trying to do in this script is the following:
Code:
1) Find all videos in ~/vids/ (this is done using: find ${HOME}/vids/ -type f \( -name "*.mp4" -o -name "*.mkv" \))
2) Find the directories the files are listed in under ~/vids/ (IE: TV/showname/season or Movies/Moviename etc) I don't know how to do this part
3) Ask the user which video they want to watch via dmenu (which would look like this):
TV:
Death Note:
Season one:
S01EP01 Rebirth.mkv
ETC
Movies:
Blade Runner 2049.mp4
Blade Runner.mp4
ETC
4) Play the video the user selected
5) If the user doesn't select a video (IE $file = nothingor they use escape which closes dmenu) exit
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.