shell 脚本常用命令,音频提取、格式转换、切割

实现一下功能:

1,mp4 视频文件提取 wav,pcm;

2,wav 切割为每段30s 的音频;

3,wav 切割后的音频转换为 pcm,ffmpeg无法将 pcm 文件切割

# 用 /bin/bash,需要执行 bash  test.sh
# 用 /bin/bash ,执行 sh test.sh,会报错,可修改为: sudo ln -s /bin/bash  /bin/sh

$0 是脚本本身的名字,$1 是给脚本传的第一个参数,$2 是传的第二个

 root_dir="./data_video"     #注意:"=" 两边不能有空格!

traversal_test.sh : 遍历文件夹

#!/bin/sh
# create date: 2022.04.14
# 用 /bin/bash,需要执行 bash  test.sh
# 用 /bin/bash ,执行 sh test.sh,会报错,可修改为: sudo ln -s /bin/bash  /bin/sh

function getdir(){
    for  element  in `ls $1`      # $0 是脚本本身的名字,$1 是给脚本传的第一个参数,$2 是传的第二个参数
    do 
        # echo $element                #文件名(不带路径)
        dir_or_file=$1"/"$element
        # echo  $dir_or_file          #文件名(带路径)
        if [ -d $dir_or_file ]        # -d filename: 如果 filename为目录,则为真
        then 
            getdir $dir_or_file   #再次调用getdir()
        else
            echo $dir_or_file
        fi 
    done
}
root_dir="./data_video"     #注意:"=" 两边不能有空格!
getdir $root_dir

if [ $suffix = 'mp4' ]    #字符串变量,注意:[]里面两边需要空格

ffmpeg_v2a.sh :将音频从视频中提取出来

#!/bin/bash
# create  by  cw, date: 2022.04.14 
# https://www.jianshu.com/p/eba436d46904
#` `和$( ) :在 bash shell 中,$()与``都是用来做命令替换的
# $和{ } 的用处:用来作变量替换
# 实现音频提取,转换,切割

# traversal for single folder 
vedio_to_audio(){
    startTime=`date +%Y.%m.%d-%H:%M:%S` 
    startTime_s=`date +%s`      #从 1970 年 1 月 1 日 00:00:00 UTC 到目前为止的秒数(时间戳)
    # echo ${PWD}                           #当前路径

    # folder="./data_video/"
    # for  file_a  in  ${folder}*
    # for  file  in  `ls   $folder`
    for  file  in  `ls   $1`            # $0 是脚本本身的名字,$1 是给脚本传的第一个参数,$2 是传的第二个参数
    do
        # echo  $file                      #文件名(不带路径)
        dir_or_file=$1'/'$file    #加上路径
        # echo  $dir_or_file       #文件名(带路径)
        in_filename=$dir_or_file
        file=${in_filename##*/}      #文件名: D01_20220330013446.mp4
        filename=${file%.*}              #无后缀: D01_20220330013446
        suffix=${file##*.}                   #后缀: mp4
        # echo $file, $filename, $suffix
        # out_filename="$1"/data_audio/"${filename}".wav""    # new  filename 
        out_filename="$1"/data_audio/"${filename}".pcm""    # new  filename 
        # out_filename="$1"/"${filename}".mp3""    # new  filename 
        # echo  $in_filename
        # echo  $out_filename

    if  [ $suffix = 'mp4' ]            #字符串变量,注意:[]里面两边需要空格
    # if  [ $num  -eq  8 ]             #整数变量
    then
        # echo  "This is a mp4 file"        # print  for  test
        # ffmpeg  -i  $in_filename  -acodec pcm_s16le  -f  s16le  -ac  1 -ar  8000  -f  wav    $out_filename           # *.wav
        ffmpeg  -i  $in_filename  -acodec pcm_s16le  -f  s16le  -ac 1  -ar  8000    $out_filename          # *.pcm
        # ffmpeg  -i  D01_20220330013446.mp4  -acodec pcm_s16le  -f  s16le  -ac  1 -ar  8000  -f  wav  D01_20220330013446.wav
        # ffmpeg  -i  D01_20220330013446.mp4  -acodec pcm_s16le  -f  s16le  -ac 1  -ar  8000  D01_20220330013446.pcm
        # ffmpeg  -i  D01_20220330013446.mp4 -q:a  0  -map  a  D01_20220330013446.mp3
    fi

done
     endTime=`date +%y.%m.%d-%H:%M:%S` 
     endTime_s=`date +%s`
     sumTime=$(( endTime_s - startTime_s )) 
     echo "$startTime ---> $endTime" "Total: $sumTime seconds"
}

# traversal for multiple folder 
function getdir(){
    startTime1=`date +%Y.%m.%d-%H:%M:%S` 
    startTime_s1=`date +%s`      #从 1970 年 1 月 1 日 00:00:00 UTC 到目前为止的秒数(时间戳)
    for  element  in `ls  $1`      # $0 是脚本本身的名字,$1 是给脚本传的第一个参数,$2 是传的第二个参数
    do 
        # echo $element               #文件名(不带路径)
        dir_or_file=$1"/"$element      #加上路径
        # echo  $dir_or_file         #文件名(带路径)
        if [ -d $dir_or_file ]           # -d filename: 如果 filename 为目录,则为真
        then 
            getdir $dir_or_file      #文件为目录,再次调用getdir()
            echo $dir_or_file        # print  for  test
        else
            # echo $dir_or_file    # print  for  test 
            ##### file processing #####
            file=${dir_or_file%/*}     #获取路径
            # echo $file                             # print  for  test
            # 如果目录不存在,则新建并处理
            if [ ! -d  "$file"/data_audio"" ];          # !-d filename: 如果目录不存在
            then
            mkdir  "$file"/data_audio""               #如果目录不存在,则新建并处理
            vedio_to_audio  $file                            # convert from vedio to audio
            echo  "$file"/data_audio"": file  has  been  created !
            else
            echo  "$file"/data_audio"": file  already  exist !
            fi
        fi 

    done
    endTime1=`date +%y.%m.%d-%H:%M:%S` 
    endTime_s1=`date +%s`
    sumTime1=$(( endTime_s1 - startTime_s1 )) 
    echo "$startTime1 ---> $endTime1" "Total: $sumTime1 seconds"
}


# traversal for multiple folder  to cut 
function getdir_cut(){
    startTime1=`date +%Y.%m.%d-%H:%M:%S` 
    startTime_s1=`date +%s`      #从 1970 年 1 月 1 日 00:00:00 UTC 到目前为止的秒数(时间戳)
    for  element  in `ls  $1`      # $0 是脚本本身的名字,$1 是给脚本传的第一个参数,$2 是传的第二个参数
    do 
        # echo $element                #文件名(不带路径)
        dir_or_file=$1"/"$element      #加上路径
        # echo  $dir_or_file          #文件名(带路径)
        # ls -lh $dir_or_file
        # mediainfo  $dir_or_file

        if [ -d $dir_or_file ];           # -d filename: 如果 filename 为目录,则为真
        then 
            getdir_cut $dir_or_file      #文件为目录,再次调用 getdir_cut()
            # echo $dir_or_file        # print  for  test
        else
            # echo $dir_or_file    # print  for  test 
            ##### file processing #####
            # file=${dir_or_file%/*}     #获取路径
            file_new=${dir_or_file%.*}        #去掉后缀
            file_suffix=${dir_or_file##*.}     #得到后缀
            # echo $file_new                      # print  for  test
            # echo  $file_suffix
            # 如果目录不存在,则新建并处理
            # if [ ! -d  "$file"/data_audio"" ];        # !-d filename: 如果目录不存在
            #  if [ ! -d  $file_new  -a  $file_suffix = 'pcm' ] ;                    # -a: and   -o: or
            if [ ! -d  $file_new  -a  $file_suffix = 'wav' ] ;                    # -a: and   -o: or
            # if [ ! -d  $file_new ] && [ $file_suffix = 'wav' ] ;           # 如果目录不存在,并且是wav文件
            then
            mkdir  $file_new           #如果目录不存在,则新建并处理
            audio_cut  $file_new                   #audio  cut  start !
            echo  $file_new: file  has  been  created !
            fi
        fi 

    done
    endTime1=`date +%y.%m.%d-%H:%M:%S` 
    endTime_s1=`date +%s`
    sumTime1=$(( endTime_s1 - startTime_s1 )) 
    echo "$startTime1 ---> $endTime1" "Total: $sumTime1 seconds"
}

audio_cut(){
    audio_in=$1
    audio_name=${audio_in##*/}       # D01_20220330013446
    # echo $audio_name               # print  for  test
    num=1
    while [ $num -le 142 ]       # -lt :小于 less than,-le :小于等于 less than and be equal to
    do
    # if  [ -e $1'.pcm' ];            #如果文件存在
    if  [ -e $1'.wav' ];            #如果文件存在
    then
        let  time_stamp=num*30
        #音频截取 -t 时间,同步
        # ffmpeg  -i  D01_20220330013446.wav  -ss 00:00:00  -t 00:00:30  output.wav 
        # ffmpeg  -i  D01_20220330013446.wav  -ss 0  -to 60  output.wav        #截取到 60s 时间戳
        # ffmpeg  -i  D01_20220330013446.wav  -ss 0  -t  30  output.wav         #截取长度为 30s
        # ffmpeg  -i  $1'.pcm'  -ss  $time_stamp  -t  30   $1/$audio_name'_'$num'.pcm'          #截取长度为 30s
        ffmpeg  -i  $1'.wav'  -ss  $time_stamp  -t  30   $1/$audio_name'_'$num'.wav'          #截取长度为 30s

        # 删除文件过小的文件!
        # 获取文件大小的四种方式
        # du -sh D01_20220330013446.wav | awk '{print $1}'
        # ls -lh D01_20220330013446.wav | awk '{print $5}'
        # wc -c D01_20220330013446.wav | awk '{print $1}'
        # stat -c "%s" D01_20220330013446.wav 

        # value=$(du -s  $1/$audio_name'_'$num'.wav' | awk '{print $1}')
        # value=$( ls -l  $1/$audio_name'_'$num'.pcm'  | awk '{print $5}')
        value=$( ls -l  $1/$audio_name'_'$num'.wav'   | awk '{print $5}')
        # value=$(du -s D01_20220330013446.wav  | awk '{print $1}')
        echo  "value:" $value
        if [ $value -le '200' ] ;     #文件大小不超过 200 bit
        then
            # rm   $1/$audio_name'_'$num'.pcm' 
            # echo "delete  $1/$audio_name'_'$num'.pcm'  success !"
            rm   $1/$audio_name'_'$num'.wav' 
            echo "delete  $1/$audio_name'_'$num'.wav'  success !"
            break
            echo  "break while loop !"
        fi

        let  num++        # num add  
    fi
    done
}


# traversal for multiple folder to transform wav  to pcm 
function getdir_wav2pcm(){
    startTime1=`date +%Y.%m.%d-%H:%M:%S` 
    startTime_s1=`date +%s`      #从 1970 年 1 月 1 日 00:00:00 UTC 到目前为止的秒数(时间戳)
    for  element  in `ls  $1`       # $0 是脚本本身的名字,$1 是给脚本传的第一个参数,$2 是传的第二个参数
    do 
        # echo $element                #文件名(不带路径)
        dir_or_file=$1"/"$element      #加上路径
        # echo  $dir_or_file          #文件名(带路径)
        if [ -d $dir_or_file ];           # -d filename: 如果 filename 为目录,则为真
        then 
            getdir_wav2pcm $dir_or_file         #文件为目录,再次调用 getdir_wav2pcm()
            # echo $dir_or_file        # print  for  test
        else
            # echo $dir_or_file    # print  for  test 
            ##### file processing #####
            file_route=${dir_or_file%/*}     #获取路径
            file_folder_name=${file_route##*/}
            file_new_pcm=${file_route%/*}'/data_pcm_cut'
            file_new=${dir_or_file%.*}        #去掉后缀   
            file_name=${file_new##*/}
            file_suffix=${dir_or_file##*.}    #得到后缀
            # echo 00$file_new                      #./data_video/data_cut/D01_20220330024453/D01_20220330024453_99
            # echo 11$file_suffix
            # echo 22$file_route                   #./data_video/data_cut/D01_20220330024453
            # echo 33$file_new_pcm          #./data_video/data_cut/data_pcm_cut
            # echo 44$file_name                  #D01_20220330024453_99
            # echo  $file_folder_name       #D01_20220330024453
            # pause()                    #程序暂停

            # 如果目录不存在,则新建并处理
             if [ ! -d  $file_new_pcm ] ;    
             then
             mkdir  $file_new_pcm         
             fi 
             if [ ! -d  $file_new_pcm'/'$file_folder_name ] ; 
             then
             mkdir  $file_new_pcm'/'$file_folder_name
             fi              

            # if [ ! -d  "$file"/data_audio"" ];        # !-d filename: 如果目录不存在
            if [ $file_suffix = 'wav' ] ;                    # -a: and   -o: or
            # if [ ! -d  $file_new ] && [ $file_suffix = 'wav' ] ;           # 如果目录不存在,并且是wav文件
            then
            file_path_pcm=$file_new_pcm'/'$file_folder_name'/'$file_name'.pcm'
            ffmpeg -i  $dir_or_file  -acodec pcm_s16le  -f  s16le  -ac 1  -ar  8000  $file_path_pcm
            echo  $file_new_pcm: file  has  been  created !
            fi
        fi 
    done
    endTime1=`date +%y.%m.%d-%H:%M:%S` 
    endTime_s1=`date +%s`
    sumTime1=$(( endTime_s1 - startTime_s1 )) 
    echo "$startTime1 ---> $endTime1" "Total: $sumTime1 seconds"
}


############### function call #################
# traversal for single folder !
# audio_dir="./data_video"
# audio_dir="/data/datasets/SED_202204/data_mp4"
# vedio_to_audio $audio_dir

# traversal for multiple folder !
# root_dir="./data_video"     #注意:"=" 两边不能有空格!
# root_dir="/data/datasets/SED_202204/data_mp4" 
# getdir $root_dir

# traversal for multiple folder to cut
# audio_dir="./data_video"
# audio_dir="/data/datasets/SED_202204/data_pcm"     # ffmpeg无法对pcm裁剪,需要wav转pcm!
# audio_dir="/data/datasets/SED_202204/data_wav" 
# getdir_cut  $audio_dir

# traversal for multiple folder to transform  wav  to pcm 
# audio_dir="./data_video/data_cut"
audio_dir="/data/datasets/SED_202204/data_wav_cut"     
getdir_wav2pcm $audio_dir

 ***************************** 获取文件大小*********************

# awk 主要用来处理文件,将文本按照指定的格式输出。其中包含变量,循环以及数组。

# awk [选项] '匹配规则和处理规则' [处理文本路径]

# awk -F: '{print $1}' /etc/passwd

# 标准输出 | awk [选项] '匹配规则和处理规则'

# cat /etc/passwd | awk -F: '{print $1}'

du
du -sh D01_20220330013446.wav | awk '{print $1}'
ls
ls -lh D01_20220330013446.wav | awk '{print $5}'
wc
wc -c D01_20220330013446.wav | awk '{print $1}'
stat
stat -c "%s" D01_20220330013446.wav

Shell 获取单个文件大小的几种方式 | 温欣爸比的博客

Shell中获取单个文件大小_rockly89的博客-CSDN博客_shell 获取文件大小

 ***************************** 分割线 ****************************

# file=${in_filename##*/}  #分别使用/和.作为分隔符来进行处理

# filename=${file%.*}

# suffix=${file##*.}

# echo $file, $filename, $suffix

# explain for #, %, ##, %% -- so useful

# ${in_filename##*/} # 从左边开始删除str中最大匹配(*/ 的字符串

# ${in_filename%/*} #从右边开始删除str中最小匹配/* 的字符串

# ${in_filename##*.} #从左边开始删除file中最大匹配*. 的字符串

# ${in_filename%.*} #从右边开始删除file中最小匹配.* 的字符串

# ${in_filename%%.*} #从右边开始删除file中最大匹配 .* 的字符串

# ${in_filename#*.} #从左边开始删除file中小匹配*. 的字符串

# #:表示从左边算起第一个

# %:表示从右边算起第一个

# ##:表示从左边算起最后一个

# %%:表示从右边算起最后一个

Linux shell中提取文件名和路径_yuyuena的博客-CSDN博客_shell获取路径中的文件名

 ***************************** 分割线 ****************************

Shell 脚本中 '$' 符号的多种用法 

通常情况下,在工作中用的最多的有如下几项:
$0:Shell 的命令本身
$1 到 $9:表示 Shell 的第几个参数
$? :显示最后命令的执行情况
$#:传递到脚本的参数个数
$$:脚本运行的当前进程 ID 号
$*:以一个单字符串显示所有向脚本传递的参数
$!:后台运行的最后一个进程的 ID 号
$-:显示 Shell 使用的当前选项

参考博客:
Shell 脚本中 '$' 符号的多种用法_Jack Tian的博客-CSDN博客_shell中$

  ***************************** 分割线 ****************************

``和$( )的区别:
在 bash shell 中,$()与``(反引号Esc键下面那个键) 都是用来做命令替换用的。
区别在于``须要额外的跳脱( \` )处理。举个例子:
 cmd1 `cmd2 \`cmd3\` `表示先执行cmd3,执行完之后交给cmd2再执行,最后再执行cmd1。

$和{ } 的用处:
用来作变量替换。
一般情况下,$var 与 ${var} 并没有啥不一样,但是用 ${ } 会比较精确的界定变量名称的范围。

( )和{ }的区别:
()和{}都是对一串的命令进行执行,但有所区别:
相同点:
()和{}都是把一串的命令放在括号里面,并且命令之间用;号隔开
不同点:
()只是对一串命令重新开一个子shell进行执行,{}对一串命令在当前shell执行
()最后一个命令可以不用分号,{}最后一个命令要用分号
()里的第一个命令和左边括号不必有空格,{}的第一个命令和左括号之间必须要有一个空格
()和{}中括号里面的某个命令的重定向只影响该命令,但括号外的重定向则影响到括号里的所有命令 

  ******************************* 整数计算****************************

二、shell变量---变量的数学运算,let i++实例_ 清欢渡.的博客-CSDN博客_shell 变量++

 expr命令_Linux expr命令:四则远算和字符串运算

整数运算:
方法一:expr
echo $(expr 2 + 4)
expr  2 \* 5
expr \( 10 + 6 \) \* 3 + 10
方法二:$(( ))
echo $((1+2*5))
方法三:$[ ]
echo $[4*5-2]
方法四:let
let sum=2**4
echo $sum


小数运算:
awk 'BEGIN{…}' 可以进行小数运算
awk 'BEGIN{print 1/3+0.1}'

$(())的使用:
用来作整数运算
在 bash 中,$(( )) 的整数运算符号大致有这些:
+ - * / :分别为 "加、减、乘、除"。
% :余数运算
& | ^ !:分别为 "AND、OR、XOR、NOT" 运算。
a=5; b=7; c=2
echo $(( a+b*c ))

(()) 用于整数之间常用的运算符,效率高
let :用于整数运算,类似于(())
let 命令的语法格式为:

let  表达式
let "表达式"
let '表达式'

例子:

i=2
let i+=2
echo $i

  ******************************* 算术比较 **************************** 

[]和[[]]的异同点:
1.相同点:
二者都支持算术比较和字符串比较表达式(具体使用可能有点不同)
条件表达式要放在方括号之间,并且要有空格,例如: [$a==$b] 是错误的,必须写成 [ $a == $b ]。
2.不同点:
"["是一条命令, 与test等价,大多数shell都支持。
"[[",是关键字,许多shell(如ash bsh)并不支持这种方式

"[":逻辑与:"-a";逻辑或:"-o";"[[":逻辑与:"&&";逻辑或:"||"

[ expr ] 等于 test expr,对 test 命令来说, 用 -eq 要进行数字比较,而你此时传入字符串,就报错了。
[[]]用 -eq 进行数字比较时,不会报错,因为它直接把非整数的字符串直接转换成了 0 

[[ ... ]]进行算术扩展,而[ ... ]不做
$ [[ 99+1 -eq 100 ]]&&echo true||echo false

四、shell中``和$()、$(())、${}、[]和[[]]使用_这个名字想了很久的博客-CSDN博客

 ***************************** 分割线 ****************************

linux 下shell中 if 的“-e,-d,-f”的意思

文件表达式
-e filename 如果 filename存在(exist),则为真
-d filename 如果 filename为目录(directory),则为真 
-f filename 如果 filename为常规文件(),则为真
-L filename 如果 filename为符号链接(link),则为真
-r filename 如果 filename可读,则为真 
-w filename 如果 filename可写,则为真 
-x filename 如果 filename可执行,则为真
-s filename 如果文件长度不为0,则为真
-h filename 如果文件是软链接,则为真
filename1 -nt filename2 如果 filename1比 filename2新,则为真。
filename1 -ot filename2 如果 filename1比 filename2旧,则为真。

整数变量表达式
-eq 等于
-ne 不等于
-gt 大于
-ge 大于等于
-lt 小于
-le 小于等于

字符串变量表达式
If  [ $a = $b ]                 如果string1等于string2,则为真
                                字符串允许使用赋值号做等号
if  [ $string1 !=  $string2 ]   如果string1不等于string2,则为真       
if  [ -n $string  ]             如果string 非空(非0),返回0(true)  
if  [ -z $string  ]             如果string 为空,则为真
if  [ $sting ]                  如果string 非空,返回0 (和-n类似) 

    逻辑非 !                   条件表达式的相反
if [ ! 表达式 ]
if [ ! -d $num ]               如果不存在目录$num

    逻辑与 –a                   条件表达式的并列
if [ 表达式1  –a  表达式2 ]

    逻辑或 -o                   条件表达式的或
if [ 表达式1  –o 表达式2 ]
 

参考资料:

linux 下shell中if的“-e,-d,-f”是什么意思

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值