【shell基础】shell常用基础语句-替换后缀名复制同名文件

script

# copy images with same name as json file to one directory
dir=/home/xxx/output_tfl_20220630
mkdir $dir/image
for file in $dir/*.json; do
    # echo $file
    pngname=${file/%.json/.png} # OK
newname=${file%.json}.png # OK cp
$pngname $dir/image # echo $pngname done

 解析

脚本最重要的部分是

pngname=${file/%.json/.png}

这部分的含义就是将字符串file的.json后缀替换成.png,还有一种写法就是匹配删除,然后在大括号后面加上要替换成的部分,

newname=${file%.json}.png

如:${file%.json}.png,这个就是将字符串的.json后缀修改为.png。

两种方法都可以的。

注意,后来发现复制的文件有可能会发生变化,比如复制一张图像,原图像是正常的,1.5M大小,复制之后发现文件内容有损坏,大小是1.2M。

 

update 20220801

如果目录不一样,但是文件名需要一致呢?

basename: 该命令的作用是从路径中提取出文件名,使用方法为basename NAME [SUFFIX]

dirname: 该命令的作用是从路径中提取出目录名,使用方法为 dirname NAME

dir=/e/04_Dataset/traffic_light/annotation
# mkdir $dir/image
for file in $dir/tfl_anno/*.json; do
    echo $file
    dirn=$(dirname $file)
    base=$(basename $file)
    echo $dirn
    echo $base
done

output:

/e/04_Dataset/traffic_light/annotation/tfl_anno/TFL_00010_20220726T132451.json
/e/04_Dataset/traffic_light/annotation/tfl_anno
TFL_00010_20220726T132451.json

update20220826

将imagedis文件中每一行的字符串images和png分别替换为labels、txt;script.sh内容如下:

#! bin/bash
imagedis=/media/xxx/dataset/traffic_light/image_dis.txt
labeldis=/media/xxx/dataset/traffic_light//label_dis.txt
# lines=$(cat image)
rm $labeldis
for line in `cat $imagedis`
do
    newname=${line%.png}.txt
    echo $newname
    # newname=${line/%images/labels}
    newname=${newname/images/labels}
    echo $newname
    echo $newname >>$labeldis # append 
    # echo $newname > $labeldis  # override
done

出现错误

bad substitution

发现只要在运行的时候使用bash script.sh即可;

update20230117

替换后缀和路径,同时使用ffmpeg命令将yuv422yuyv格式转换为rgb24的png格式。

#! bin/bash
dir=/media/xxx/dataset/traffic_light
mkdir $dir/yuv2png
yuv=testdata
png=yuv2png
for line in $dir/$yuv/*.yuv; do
    newname=${line%.yuv}.png
    echo $newname
    pngname=${newname/$yuv/$png}
    ffmpeg -s 1280*720 -pix_fmt yuyv422 -i $line -pix_fmt rgb24 $pngname
done

运行

bash ./yuv2png.sh

 update20230118

替换路径,将yuv422yuyv格式转为nv12格式,因为TDA4中app_tidl_od中的测试程序默认输入图像yuv格式是nv12,这样才能得到正确结果。

同时,将nv12格式的yuv文件的名称按序修改为占位为10个数字且高位补零

#! bin/bash
# yuv2nv12.sh
dir=/media/xxx/dataset/traffic_light yuv=testdata nv12=nv12 # yuv422yuyv to nv12 for line in $dir/$yuv/*.yuv; do newname=${line/$yuv/$nv12} ffmpeg -s 1280*720 -pix_fmt yuyv422 -i $line -pix_fmt nv12 $newname done # rename testlist=testlist mkdir $dir/$testlist n=0 for line in $dir/$nv12/*.yuv; do let n++ dirn=$(dirname $line) newname=$dirn/$(printf "%010d.yuv" $n) newname=${newname/$nv12/$testlist} cp $line $newname done

出现错误

let:not found

只要在运行的时候使用bash yuv2nv12.sh即可;

原因:/bin/sh 指向了 dash 而不是 bash , dash 不支持 let 命令;

update20230202

批量修改文件名,文件名添加前缀或者后缀;

类似于,文件名oldname.png,添加前缀改为new_oldname.png,添加后缀改为oldname_20230116.png;

# rename with prefix or suffix.
dir=/media/01_dataset/traffic_light/tflvideo
yuv2png=yuv2png
png=png
for file in $dir/$yuv2png/*.png; do
    echo $file
    dirn=$(dirname $file)
    base=$(basename $file)
    # prefix="new_"$base
    # newnamep=$dirn/$prefix
    # suffix=`echo $file|sed -r 's/(.*)(\..*)/\1_20230116\2/g'`
    suffix=`echo $base|sed -r 's/(.*)(\..*)/\1_20230116\2/g'`
    newnames=$dirn/$suffix
    # echo $prefix
    # echo $newnamep
    # echo $suffix
    # echo $newnames
    newname=${newnames/$yuv2png/$png}
    echo $newname
    cp $file $newname
done

 update20230214   指定多个目录循环查询执行

# yuyv2png
dir=/media/01_dataset/traffic_light/tflvideo
mkdir $dir/yuv2png
# yuv=202302101
png=yuv2png
# echo $png
for files in 20230116 202302100 202302101 202302102 202302140 202302141; do
    # echo $files
    yuv=$files
    echo $yuv
    for file in $dir/$yuv/*.yuv; do
        echo $file
        # pngname=${file/%.json/.png}
        newname=${file%.yuv}.png
        # echo $newname
        pngname=${newname/$yuv/$png}
        # echo $pngname
        dirn=$(dirname $pngname)
        base=$(basename $pngname)
        prefix=$yuv"_"$base
        # echo $prefix
        # suffix=`echo $base|sed -r 's/(.*)(\..*)/\1_202302101\2/g'`
        addtime=$dirn/$prefix
        # echo $suffix
        echo $addtime
        # name=${addtime/$yuv/$png}
        # # cp $pngname $dir/image
        ffmpeg -s 1280*720 -pix_fmt yuyv422 -i $file -pix_fmt rgb24 $addtime
    done
done
View Code

update20231205 间隔一定数目进行特定操作(取余)

script_path="$(pwd)"
n=0
mkdir $script_path/filterdata
# 间隔一定数目操作
for one in $script_path/badbehavior1/*.png; do
    let n++
    ((tmp=$n %5))
    if [ "$tmp" == 0 ]; then
        mv $one $script_path/filterdata
    fi
done

 取余操作:

#!/bin/bash
for var in `seq 1 19`; do
        # echo $var
        ((tmp=$var %5))
        if [ "$tmp" == 0 ]; then
            echo $var
        fi
done

update20240423   获取某个目录下某种格式的文件的数量

# source /opt/vision_apps/vision_apps_init.sh
dir=/home/root/dms
for filename in testimg_fbb0 testimg_fbb1 testimg_fbb2 testimg_fbb3 testimg_fbb4 testimg_fcc0 testimg_fcc1 testimg_fcc2 testimg_fcc4; do
    echo $filename
    # name=$filename
    # echo $name
    rm -r testimg
    mkdir temp
    cnt=$(find "$dir/image/$filename/" -type f -name "*.png" | wc -l)
    mv $dir/image/$filename/*.png $dir/temp
    bash ./rename.sh
    rm -r output
    mkdir output
sed -i "s/num_frames  1000/num_frames  $cnt/" dmsbhv/app_od_dmsbhv.cfg # ./vx_app_tidl_od_dmsbhv_c3imglist.out --cfg dmsbhv/app_od_dmsbhv.cfg > log_dmsbhv.txt done

关键语句

cnt=$(find "$dir/image/$filename/" -type f -name "*.png" | wc -l)  #获取某目录中某类型文件的数量
sed -i "s/num_frames  1000/num_frames  $cnt/" dmsbhv/app_od_dmsbhv23183.cfg #修改配置文件中某参数

sed命令使用-i选项直接修改文件内容,注意,sed命令的替换操作是全局的。

s/num_frames  1000/num_frames  $cnt/   # 这是一个替换操作,$cnt是脚本接收的参数。

20240430 删除前导零,获取文件某行内容

root=/c/test0p6
imgfalse=img_false
imgmiss=img_miss
testfalse=test_false
testmiss=test_miss
imgroot=/d/TDA4/JKL/bad23183/driverdata/retain
txtdir=_txtfile
# 1. 根据false目录中每个子目录的每个文件名称,获取名称中的数字,
# 2. 在txt文件中对应的数字行得到原图像名称,复制图像
cd $root/$testfalse
n=0
for dir in `ls .`; do
    echo "dir= $dir"
    dirn="${dir//false_/}"
    # echo "dirn= $dirn"
    filename=${dirn}.txt
    txtfile=$imgroot/$txtdir/$filename
    # echo "txtfile= $txtfile"
    if [ $n -gt 1 ]; then
        break
    fi
    for file in $root/$testfalse/$dir/*.png; do
        base=$(basename $file) # dmsbhv_0000000809.png
        # echo "base= $base"
        strk=$base
        temp="${strk//dmsbhv_/}"
        temp="${temp//.png/}"
        k=$(echo "$temp" | sed 's/^0*//') # delete前导零
        # echo "k= $k"
        # imgname=$(awk "NR==${k}" $txtfile) # OK获取文件某行内容
        imgname=$(sed -n "${k}p" $txtfile) # OK获取文件某行内容
        # echo "imgname= $imgname"
        temp=testimg_
        imgdir="$temp$dirn"
        # echo "imgdir= $imgdir"
        # echo "src= $imgroot/$imgdir/$imgname"
        # echo "dst= $root/$imgfalse"
        cp $imgroot/$imgdir/$imgname $root/$imgfalse
    done
    let n++
done
View Code

关键语句

temp="0000000809"
txtfile=aaa.txt
k=$(echo "$temp" | sed 's/^0*//') # delete前导零
# imgname=$(awk "NR==${k}" $txtfile) # OK获取文件某行内容
imgname=$(sed -n "${k}p" $txtfile) # OK获取文件某行内容
n=0
if [ $n -gt 1 ]; then
    break
fi

 再有注意字符串替换、if语句以及添加前缀、后缀;

-gt:大于,greater than
-eq:等于,equal
-lt:小于,less than
-ge:大于等于,greater than or equal
-le:小于等于,less than or equal
-ne:不等于,not equal

注意break和continue的用法;

 

 

 

 

参考

1. shell获取文件名和文件目录

2. 【shell篇】流程控制-CSDN博客

posted on 2022-07-06 13:02  鹅要长大  阅读(448)  评论(0编辑  收藏  举报

导航