Bash
圍繞現有循環建構一個 for 循環,以替換使用者輸入
我基本上有這個腳本:
#!/bin/bash #Asks For filname and Word echo 'Which word are you looking for?' read word echo 'What's the name of the file?' read fileName #Searches word and parses the line-numbers wordOut=$(grep -i -n -w $word $fileName.srt |cut -f1 -d:) #Sets all outputs to diffrent line numbers and saves a temp file for word in $wordOut do echo $word done >file.tmp #Parses lines to array, removes temp file mapfile -t arr <file.tmp rm file.tmp #Declares variable for the number of array entries (not used anywhere atm) ln=${#arr[@]} #Subtract all array entries with one one=1 for i in "${arr[@]}" do crc=`expr $i - $one` echo $crc done >two.tmp #Subtraction result to array2 mapfile -t arr2 <two.tmp rm two.tmp echo ${arr2[@]} #retrieve times for h in "${arr2[@]}" do line=$(sed "${h}q;d" $fileName.srt) echo $line done >three.tmp #replace all commas with decimal points sed 's/,/./g' three.tmp >four.tmp #remove temp file 3 and parse 'decimal pointed' to array rm three.tmp mapfile -t arr3 <four.tmp rm four.tmp echo ${arr3[0]} echo ${arr3[1]} # converts HH:MM:SS.sss to fractional seconds codes2seconds() ( local hh=${1%%:*} local rest=${1#*:} local mm=${rest%%:*} local ss=${rest#*:} printf "%s" $(bc <<< "$hh * 60 * 60 + $mm * 60 + $ss") ) # converts fractional seconds to HH:MM:SS.sss seconds2codes() ( local seconds=$1 local hh=$(bc <<< "scale=0; $seconds / 3600") local remainder=$(bc <<< "$seconds % 3600") local mm=$(bc <<< "scale=0; $remainder / 60") local ss=$(bc <<< "$remainder % 60") printf "%02d:%02d:%06.3f" "$hh" "$mm" "$ss" ) subtracttimes() ( local t1sec=$(codes2seconds "$1") local t2sec=$(codes2seconds "$2") printf "%s" $(bc <<< "$t2sec - $t1sec") ) for range in "${arr3[@]}" do mod=$(sed 's/[^0-9]//g' <<< $range) duration=$(subtracttimes "${range%% -->*}" "${range##*--> }") printf "%s\n" "ffmpeg -i $fileName.mp4 -ss ${range%% -->*} -t $duration -async 1 $word.$mod.$fileName.cut.mp4" done >final.tmp sudo chmod 755 final.tmp ./final.tmp rm final.tmp
效果很好。它的作用:它在 srt 文件中搜尋具有相同名稱的 mp4 文件中的關鍵字,然後找到與該關鍵字匹配的時間戳,並將影片從起點剪切到終點。
SRT 文件,例如:
**video.srt** 1 00:00:00,000 --> 00:00:04,950 welkom bij eerste toekomst reizen dus 2 00:00:02,639 --> 00:00:05,670 onderdeel aan de achterhoekse toekomst 3 00:00:04,950 --> 00:00:07,290 stoere 4 00:00:05,670 --> 00:00:11,250 mijn heren nu al heel veel dingen
所以基本上,如果你正在尋找關鍵字“toekomst”,它會輸出兩個 mp4,一個最初開始於
00:00:00,000
並結束於00:00:04,950
,一個開始於00:00:02,639
結束於00:00:05,670
。我在同一個目錄中有多個 MP4,它們都有一個與 mp4 同名的對應 .srt 文件,它們都需要通過這個腳本執行。所以我想建構一個腳本擴展來查找所有具有相同名稱的文件,並通過腳本執行它。
所以我寫了這段程式碼來測試這個:
#!/bin/bash cd "`dirname "$0"`" for file in *.srt do fileName="$( basename "$file" .srt)" echo $fileName echo $fileName.mp4 echo $fileName.srt done >temp
它確實給出了目錄中所有 .mp4 文件和 .srt 文件的輸出:
h h.mp4 h.srt r r.mp4 r.srt
因此,我圍繞現有程式碼建構了這個 for 循環,如下所示:
#!/bin/bash cd "`dirname "$0"`" #Asks For filname and Word echo 'Which word are you looking for?' read word for file in *.srt do fileName="$( basename "$file" .srt)" #Searches word and parses the line-numbers wordOut=$(grep -i -n -w $word $fileName.srt |cut -f1 -d:) #Sets all outputs to diffrent line numbers and saves a temp file for word in $wordOut do echo $word done >file.tmp #Parses lines to array, removes temp file mapfile -t arr <file.tmp rm file.tmp #Declares variable for the number of array entries (not used anywhere atm) ln=${#arr[@]} #Subtract all array entries with one one=1 for i in "${arr[@]}" do crc=`expr $i - $one` echo $crc done >two.tmp #Subtraction result to array2 mapfile -t arr2 <two.tmp rm two.tmp echo ${arr2[@]} #retrieve times for h in "${arr2[@]}" do line=$(sed "${h}q;d" $fileName.srt) echo $line done >three.tmp #replace all commas with decimal points sed 's/,/./g' three.tmp >four.tmp #remove temp file 3 and parse 'decimal pointed' to array rm three.tmp mapfile -t arr3 <four.tmp rm four.tmp echo ${arr3[0]} echo ${arr3[1]} # converts HH:MM:SS.sss to fractional seconds codes2seconds() ( local hh=${1%%:*} local rest=${1#*:} local mm=${rest%%:*} local ss=${rest#*:} printf "%s" $(bc <<< "$hh * 60 * 60 + $mm * 60 + $ss") ) # converts fractional seconds to HH:MM:SS.sss seconds2codes() ( local seconds=$1 local hh=$(bc <<< "scale=0; $seconds / 3600") local remainder=$(bc <<< "$seconds % 3600") local mm=$(bc <<< "scale=0; $remainder / 60") local ss=$(bc <<< "$remainder % 60") printf "%02d:%02d:%06.3f" "$hh" "$mm" "$ss" ) subtracttimes() ( local t1sec=$(codes2seconds "$1") local t2sec=$(codes2seconds "$2") printf "%s" $(bc <<< "$t2sec - $t1sec") ) for range in "${arr3[@]}" do mod=$(sed 's/[^0-9]//g' <<< $range) duration=$(subtracttimes "${range%% -->*}" "${range##*--> }") printf "%s\n" "ffmpeg -i $fileName.mp4 -ss ${range%% -->*} -t $duration -async 1 $word.$mod.$fileName.cut.mp4" done >final.tmp sudo chmod 755 final.tmp ./final.tmp rm final.tmp done
第一次執行時,第一個文件給出了正確的輸出 mp4,但之後它以某種方式對變數進行了洗牌,我無法獲得正確的輸出。
我自己通過使用另一個腳本並將變數導出到主腳本來修復它,所以最後我使用了這兩個腳本。 主腳本:
#!/bin/bash echo 'Welk woord zoek je?' read word export word for file in *.srt do fileName="$( basename "$file" .srt)" export fileName ./actualScript done
實際腳本:
#!/bin/bash #Asks For filname and Word #Searches word and parses the line-numbers wordOut=$(grep -i -n -w $word $fileName.srt |cut -f1 -d:) #Sets all outputs to diffrent line numbers and saves a temp file for word in $wordOut do echo $word done >file.tmp #Parses lines to array, removes temp file mapfile -t arr <file.tmp rm file.tmp #Declares variable for the number of array entries (not used anywhere atm) ln=${#arr[@]} #Subtract all array entries with one one=1 for i in "${arr[@]}" do crc=`expr $i - $one` echo $crc done >two.tmp #Subtraction result to array2 mapfile -t arr2 <two.tmp rm two.tmp echo ${arr2[@]} #retrieve times for h in "${arr2[@]}" do line=$(sed "${h}q;d" $fileName.srt) echo $line done >three.tmp #replace all commas with decimal points sed 's/,/./g' three.tmp >four.tmp #remove temp file 3 and parse 'decimal pointed' to array rm three.tmp mapfile -t arr3 <four.tmp rm four.tmp echo ${arr3[0]} echo ${arr3[1]} # converts HH:MM:SS.sss to fractional seconds codes2seconds() ( local hh=${1%%:*} local rest=${1#*:} local mm=${rest%%:*} local ss=${rest#*:} printf "%s" $(bc <<< "$hh * 60 * 60 + $mm * 60 + $ss") ) # converts fractional seconds to HH:MM:SS.sss seconds2codes() ( local seconds=$1 local hh=$(bc <<< "scale=0; $seconds / 3600") local remainder=$(bc <<< "$seconds % 3600") local mm=$(bc <<< "scale=0; $remainder / 60") local ss=$(bc <<< "$remainder % 60") printf "%02d:%02d:%06.3f" "$hh" "$mm" "$ss" ) subtracttimes() ( local t1sec=$(codes2seconds "$1") local t2sec=$(codes2seconds "$2") printf "%s" $(bc <<< "$t2sec - $t1sec") ) for range in "${arr3[@]}" do mod=$(sed 's/[^0-9]//g' <<< $range) duration=$(subtracttimes "${range%% -->*}" "${range##*--> }") printf "%s\n" "ffmpeg -i $fileName.mp4 -ss ${range%% -->*} -t $duration -async 1 $word.$mod.$fileName.cut.mp4" done >final.tmp sudo chmod 755 final.tmp ./final.tmp rm final.tmp