LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 04-16-2023, 10:07 AM   #1
GPGAgent
Senior Member
 
Registered: Oct 2018
Location: Surrey UK
Distribution: Mint 20 xfce 64bit
Posts: 1,026
Blog Entries: 3

Rep: Reputation: 133Reputation: 133
Question BASH - script to loop through files in size order descending


I can write a simple for loop to loop through files in name order.
Code:
 for ff in *.mp4; do HandBrakeCLI -i "$ff" -o "X$ff";done
This works fine with a command in the do section to process the $ff file

But I want the list in size order descending so I did this
Code:
for ff in "$( ls *.mp4 | sort -r )"; do echo "$ff"; done
which results in this
Code:
$ for ff in "$( ls *.mp4 | sort -r )"; do echo "$ff"; done;
X BIG.mp4
CMID.mp4
BMID.mp4
ASMALL.mp4
Fine I thought, sorted in size order escending, just need to put my command in the do section
Code:
for ff in "$( ls *.mp4 | sort -r )"; do HandBrakeCLI -i "$ff" -o "X$ff"; done
But I was wrong, there is a /n hidden in $ff whcih lets it display but not much use sending the whole list of files to HandBrakeCLI in one hit.
The result
Code:
$ for ff in "$( ls *.mp4 | sort -r )"; do HandBrakeCLI -i "$ff" -o "X$ff"; done;
[16:03:52] hb_init: starting libhb thread
[16:03:52] thread 7fbf823a0700 started ("libhb")
HandBrake 1.3.1 (2020032300) - Linux x86_64 - https://handbrake.fr
16 CPUs detected
Opening X BIG.mp4
CMID.mp4
BMID.mp4
ASMALL.mp4...
[16:03:52] CPU: Intel(R) Xeon(R) CPU           E5620  @ 2.40GHz
[16:03:52]  - logical processor count: 16
[16:03:52] hb_scan: path=X BIG.mp4
CMID.mp4
BMID.mp4
ASMALL.mp4, title_index=1
disc.c:323: failed opening UDF image X BIG.mp4
CMID.mp4
BMID.mp4
ASMALL.mp4
disc.c:424: error opening file BDMV/index.bdmv
disc.c:424: error opening file BDMV/BACKUP/index.bdmv
....
..
......
How do I seperate the list into individual movies to be processed squentially?

Note: Some files have spaces in their names

Last edited by GPGAgent; 04-16-2023 at 10:11 AM.
 
Old 04-16-2023, 10:39 AM   #2
GPGAgent
Senior Member
 
Registered: Oct 2018
Location: Surrey UK
Distribution: Mint 20 xfce 64bit
Posts: 1,026

Original Poster
Blog Entries: 3

Rep: Reputation: 133Reputation: 133
I've tried something else, I've made a file of the movie names in descending size order, simple enough
Code:
$ ls *.mp4 | sort -r > x.x
$ cat x.x
X BIG.mp4
CMID.mp4
BMID.mp4
ASMALL.mp4
$
So now just read that file with a while loop
Code:
$ while read ff; do echo $ff; done < x.x
X BIG.mp4
CMID.mp4
BMID.mp4
ASMALL.mp4
$
And that works fine, so now put the HandBrakeCLI command in
Code:
$ while read ff; do HandBrakeCLI -i "$ff" -o "X$ff" --stop-at seconds:20; done < x.x
[16:36:34] hb_init: starting libhb thread
[16:36:34] thread 7f55a33bd700 started ("libhb")
HandBrake 1.3.1 (2020032300) - Linux x86_64 - https://handbrake.fr
16 CPUs detected
Opening X BIG.mp4...
[16:36:34] CPU: Intel(R) Xeon(R) CPU           E5620  @ 2.40GHz
[16:36:34]  - logical processor count: 16
[16:36:34] hb_scan: path=X BIG.mp4, title_index=1
....
..
x264 [info]: Weighted P-Frames: Y:1.0% UV:0.0%
x264 [info]: ref P L0: 63.7%  7.1% 21.8%  7.3%  0.1%
x264 [info]: ref B L0: 87.1% 10.3%  2.6%
x264 [info]: ref B L1: 97.7%  2.3%
x264 [info]: kb/s:1401.61
[16:36:46] mux: track 0, 600 frames, 3507325 bytes, 1399.20 kbps, fifo 1024
[16:36:46] mux: track 1, 939 frames, 5702 bytes, 2.27 kbps, fifo 1024
[16:36:46] Finished work at: Sun Apr 16 16:36:46 2023

[16:36:46] libhb: work result = 0

Encode done!

HandBrake has exited.
$
But only processes the first line!!!!

I thought I'd cracked it!
 
Old 04-16-2023, 11:03 AM   #3
elgrandeperro
Member
 
Registered: Apr 2021
Posts: 415
Blog Entries: 2

Rep: Reputation: Disabled
My guess is that handbrake is sending signals which is killing the shell.

Try this:

Code:
(while read ff; do HandBrakeCLI -i "$ff" -o "X$ff" --stop-at seconds:20; done)< x.x
 
Old 04-16-2023, 11:09 AM   #4
GPGAgent
Senior Member
 
Registered: Oct 2018
Location: Surrey UK
Distribution: Mint 20 xfce 64bit
Posts: 1,026

Original Poster
Blog Entries: 3

Rep: Reputation: 133Reputation: 133
Quote:
Originally Posted by elgrandeperro View Post
My guess is that handbrake is sending signals which is killing the shell.
Try this:
Code:
(while read ff; do HandBrakeCLI -i "$ff" -o "X$ff" --stop-at seconds:20; done)< x.x
That was my thought, but now your suggestion also stopped after processing the first line.

I know I will kick myself when I work it out or someone else does
 
Old 04-16-2023, 11:38 AM   #5
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,818

Rep: Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211
Code:
for ff in "$( ls *.mp4 | sort -r )"; do
This does not work because $( ) becomes a string that is protected by the quotes.
Without the quotes the string is subject to word splitting (partly desired) and filename generation (not desired).
The best solution is a while-read loop
Code:
ls *.mp4 | sort -r | while IFS= read -r ff; do
Each read reads one line. IFS="" and -r turn
off some magic in read.
Commands in the loop body that can read from stdin would compete with the read, and should be redirected </dev/null
If HandBrakeCLI is such a command:
Code:
</dev/null HandBrakeCLI ...
Regarding
ls *.mp4 | sort -r
This is not by size but reverse alphabetical, like
ls -r *.mp4

Last edited by MadeInGermany; 04-16-2023 at 11:54 AM.
 
1 members found this post helpful.
Old 04-16-2023, 11:57 AM   #6
GPGAgent
Senior Member
 
Registered: Oct 2018
Location: Surrey UK
Distribution: Mint 20 xfce 64bit
Posts: 1,026

Original Poster
Blog Entries: 3

Rep: Reputation: 133Reputation: 133
Quote:
Originally Posted by MadeInGermany View Post
Code:
for ff in "$( ls *.mp4 | sort -r )"; do
This does not work because $( ) becomes a string that is protected by the quotes.
Without the quotes the string is subject to word splitting (partly desired) and filename generation (not desired).
The best solution is a while-read loop
Code:
ls *.mp4 | sort -r | while IFS= read -r ff; do
Each read reads one line. IFS="" and -r turn
off some magic in read.
Commands in the loop body that can read from stdin would compete with the read, and should be redirected </dev/null
If HandBrakeCLI is such a command:
Code:
</dev/null HandBrakeCLI ...
Regarding
ls *.mp4 | sort -r
This is not by size but reverse alphabetical, like
ls -r *.mp4
You're absolutely correct about it NOT sorted by size, my mistake. Thanks for pointing that out.

Anyway I trid it like this
Code:
ls *.mp4 | sort -r | while IFS= read -r ff; do HandBrakeCLI -i "$ff" -o "X$ff" --stop-at seconds:20 ; done
but yet again it stopped after processing the first file!

Last edited by GPGAgent; 04-16-2023 at 12:01 PM.
 
Old 04-16-2023, 12:08 PM   #7
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,818

Rep: Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211
Try the </dev/null
Code:
ls *.mp4 | sort -r | while IFS= read -r ff; do </dev/null HandBrakeCLI -i "$ff" -o "X$ff" --stop-at seconds:20 ; done
 
Old 04-16-2023, 12:16 PM   #8
GPGAgent
Senior Member
 
Registered: Oct 2018
Location: Surrey UK
Distribution: Mint 20 xfce 64bit
Posts: 1,026

Original Poster
Blog Entries: 3

Rep: Reputation: 133Reputation: 133
Quote:
Originally Posted by MadeInGermany View Post
Try the </dev/null
Code:
ls *.mp4 | sort -r | while IFS= read -r ff; do </dev/null HandBrakeCLI -i "$ff" -o "X$ff" --stop-at seconds:20 ; done
Cheers that worked, can you explain why the </dev/null kept it in the loop please?

Next step is to feed it a list by size, I think this might do it
Code:
ls *.mp4 -S
Don't forget some of the file names have spaces!

And yes this worked just fine
Code:
ls *.mp4 -S | sort -r | while IFS= read -r ff; do </dev/null HandBrakeCLI -i "$ff" -o "Y$ff" --stop-at seconds:20 ; done

Last edited by GPGAgent; 04-16-2023 at 12:20 PM.
 
Old 04-16-2023, 01:02 PM   #9
teckk
LQ Guru
 
Registered: Oct 2004
Distribution: Arch
Posts: 5,147
Blog Entries: 6

Rep: Reputation: 1834Reputation: 1834Reputation: 1834Reputation: 1834Reputation: 1834Reputation: 1834Reputation: 1834Reputation: 1834Reputation: 1834Reputation: 1834Reputation: 1834
Lots of ways of doing that with bash and friends.

Few Examples:

Sort files by size.
Code:
find *.mp4 -type f -exec du -h {} + | sort -rh
find *.mp4 -type f -exec ls -lS {} +
Code:
files1=(*.mp4)
files2=($(du -a <<< "$files1" | sort -nr))

printf '%s\n' "${files2[@]}"

for i in "${files1[@]}"; do
    echo "$i"
    sleep 1
done

for i in "${files2[@]}"; do
    echo ${i##*/}
    sleep 1
done

#First will fail, the rest will be ok
for i in "${files2[@]}"; do
    echo "HandBrakeCLI -i ${i##*/} -o New_${i##*/}"
    sleep 1
done

Last edited by teckk; 04-16-2023 at 01:06 PM.
 
1 members found this post helpful.
Old 04-16-2023, 01:57 PM   #10
MadeInGermany
Senior Member
 
Registered: Dec 2011
Location: Simplicity
Posts: 2,818

Rep: Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211Reputation: 1211
If ls can sort it, do not re-sort it by piping to sort!
Perhaps you want to reverse the order, then you must tell the ls to do it:
Code:
ls *.mp4 -rS | while ...
Regarding the </dev/null, I tried to explain it.
The loop's stdin is fed by the pipe.
Not only the read can read a line from the stdin.
Obviously the HandBrakeCLI reads from the stdin, too. And "steals" it, so the read doesn't get it.
 
1 members found this post helpful.
Old 04-16-2023, 03:55 PM   #11
GPGAgent
Senior Member
 
Registered: Oct 2018
Location: Surrey UK
Distribution: Mint 20 xfce 64bit
Posts: 1,026

Original Poster
Blog Entries: 3

Rep: Reputation: 133Reputation: 133
Quote:
Originally Posted by MadeInGermany View Post
If ls can sort it, do not re-sort it by piping to sort!
Perhaps you want to reverse the order, then you must tell the ls to do it:
Code:
ls *.mp4 -rS | while ...
Regarding the </dev/null, I tried to explain it.
The loop's stdin is fed by the pipe.
Not only the read can read a line from the stdin.
Obviously the HandBrakeCLI reads from the stdin, too. And "steals" it, so the read doesn't get it.
Sorry, I did read your original post, but it didn't register in my 72yr old brain!!
 
Old 04-16-2023, 03:55 PM   #12
GPGAgent
Senior Member
 
Registered: Oct 2018
Location: Surrey UK
Distribution: Mint 20 xfce 64bit
Posts: 1,026

Original Poster
Blog Entries: 3

Rep: Reputation: 133Reputation: 133
Thanks all, I've learn't a bit more now, enough to be dangerous!!
 
  


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
Putty sort list in descending order, and show command to display softlinks erinprime Linux - Newbie 2 07-27-2015 12:55 PM
Sorting file data in descending order DNG Linux - Newbie 3 07-01-2015 12:49 AM
Ascending or descending order for poll results? linuxlover.chaitanya LQ Suggestions & Feedback 3 02-09-2011 11:24 PM
[SOLVED] Sort in descending order according to a column of an array flea89 Linux - Newbie 3 03-14-2010 06:00 PM
how to list folder size in descending order ? Winanjaya Linux - Server 2 02-09-2010 12:32 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

All times are GMT -5. The time now is 11:05 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