xargs 如何将命令串在一起

xargs 如何将命令串在一起

大家好,我是一名新手脚本编写者,没有接受过正规的编程培训,因此对于混乱的代码我深表歉意。

我想要实现的目标:

目录看起来是这样的。

/home/AAA 

/home/BBB 

/home/CCC

/home/AAA/aaaa.S01.aaa

/home/AAA/zzzz.S02.zzz

/home/AAA/xxx.S03.xxx

/home/AAA/aaaa.S01.aaa/bbbb.s01e01.bbbb.mkv

我想制作目录 AAA 的 torrent,将 cd 放到两级目录中,制作第一个 .mkv 的 mediainfo 文件,制作相同文件的缩略图,cd 到 AAA,mkdir 文件,将所有 jpg、txt 和 torrent 文件从子目录移动到文件中。对 BBB 和 CCC 等执行相同的操作。这都是电视节目,因此一般命名方案是父目录,其中包含 tv.show1、tv.show2 等。每个电视节目都有季,从第 1 季开始,目录名称中包含 S01,每个季文件夹中都有遵循标准命名结构的 mkv 文件,即 s01e01、s01e02

我编写了一个脚本,该脚本仅在有一个子目录时才有效。我确定我使用 xargs 的方式完全错误,但它似乎可以解决问题。有人能帮我修复这个问题并在每个目录上循环运行整个命令吗?谢谢

#!/bin/bash

ls | xargs -I {} mktorrent -p -v -l 24 -a https://tracker/announce -o {}.torrent {} && rm privatehd.sh.torrent && cd *S0* && mediainfo *01* > mediainfo.txt && ffmpeg -ss 00:03:45 -i *01* -vframes 1 -q:v 2 thumb.jpg && ffmpeg -ss 00:09:45 -i *01* -vframes 1 -q:v 2 thumb1.jpg && ffmpeg -ss 00:15:45 -i *01* -vframes 1 -q:v 2 thumb2.jpg && ffmpeg -ss 00:18:45 -i *01* -vframes 1 -q:v 2 thumb3.jpg && ffmpeg -ss 00:20:45 -i *01* -vframes 1 -q:v 2 thumb4.jpg && cd ../ && mkdir phd && mv **/*.jpg ./phd && mv **/*.txt ./phd && mv *.torrent ./phd && mv **/*.ass ./phd

它能做什么

ls | xargs -I {} mktorrent -p -v -l 24 -a https://tracker/announce -o {}.torrent {}

制作每个子目录的 torrent,但我现在使用的方式是一个文件夹和 .sh 文件

&& rm privatehd.sh.torrent

删除 extra.torrent 文件

&& cd *S0* && mediainfo *01* > mediainfo.txt 

cd 到包含字符串 S0 的文件夹,需要将其更改为 S01 才能处理新文件,为包含字符串 01 的文件生成 mediainfo 并保存到 txt

&& ffmpeg -ss 00:03:45 -i *01* -vframes 1 -q:v 2 thumb.jpg && ffmpeg -ss 00:09:45 -i *01* -vframes 1 -q:v 2 thumb1.jpg && ffmpeg -ss 00:15:45 -i *01* -vframes 1 -q:v 2 thumb2.jpg && ffmpeg -ss 00:18:45 -i *01* -vframes 1 -q:v 2 thumb3.jpg && ffmpeg -ss 00:20:45 -i *01* -vframes 1 -q:v 2 thumb4.jpg

使用 ffmpeg 根据不同的时间戳制作 5 个缩略图

 && cd ../ && mkdir phd && mv **/*.jpg **/*.txt *.torrent ./phd

清理。cd 向上一级创建新目录,将生成的文件移动到该目录。

&& mv **/*.ass ./phd

命令一直失败,所以我添加了这个,它起作用了,但我想我最后没有使用 {},这是为什么?但添加这个无意义的命令使得之前的所有东西都运行正常,而这个命令失败了。这没关系。

正如我所说,我是一个糟糕的脚本编写者。我花了几个小时试图找出一种方法,让我可以循环使用该命令遍历父级的每个子目录。但需要 cd 到 2 个级别,而不是像示例中那样到 1 个级别。

不确定这是否有意义,很高兴提供更多信息。

谢谢

这是在单个目录上运行我编写的脚本之前和之后的情况。之前https://prnt.sc/u3ul9shttps://prnt.sc/u3ullj https://prnt.sc/u3ulph

答案1

将许多命令串在一起&&是一种不好的形式(很快就会变得不可读,而且你不能设置变量,也很难添加注释,如上所示)。所以

  1. 制作一个使用位置参数来指定要处理的目录的脚本。
#! /bin/bash
echo Working on directory "$1"
  1. 脚本的第一行之一可以是set -e在发生错误时使脚本退出(尽管从长远来看,最好检查返回代码)
  2. 然后你可以每行放一个语句
#! /bin/bash
set-e
echo Working on directory "$1"

mktorrent -p -v -l 24 -a https://tracker/announce -o "$1".torrent "$1"
rm privatehd.sh.torrent
cd *S0*
mediainfo *01* > mediainfo.txt
ffmpeg -ss 00:03:45 -i *01* -vframes 1 -q:v 2 thumb.jpg
ffmpeg -ss 00:09:45 -i *01* -vframes 1 -q:v 2 thumb1.jpg
ffmpeg -ss 00:15:45 -i *01* -vframes 1 -q:v 2 thumb2.jpg
ffmpeg -ss 00:18:45 -i *01* -vframes 1 -q:v 2 thumb3.jpg
ffmpeg -ss 00:20:45 -i *01* -vframes 1 -q:v 2 thumb4.jpg
cd ../
mkdir phd
mv **/*.jpg ./phd
mv **/*.txt ./phd
mv *.torrent ./phd
mv **/*.ass ./phd
  1. 一旦脚本在一个目录上运行,您就可以通过在命令提示符中输入以下内容在多个目录上调用它:
for d in directorypattern*/; do the_script "$d" ; done 
  1. 当脚本运行良好时,您可以将脚本主体设为一个函数,然后在脚本中添加一行来循环传递作为多个参数的目录
#! /bin/bash
function process_directory {
    echo Working on directory "$1"
    #  More code here
}

for dir in "$@"; 
do 
    process_directory "$dir"
done

调用方式为:

the_script_for_all_dirs directorypattern*/

答案2

我决定放弃 xargs,转而使用一个带有几个变量的简单循环,效果很好,但我有点过度添加了颜色、多个种子、多个跟踪器等。编程很有趣 :D

    #!/bin/bash
    
    set -e

    BLACK="\033[30m"
    RED="\033[31m"
    GREEN="\033[32m"
    YELLOW="\033[33m"
    BLUE="\033[34m"
    PINK="\033[35m"
    CYAN="\033[36m"
    WHITE="\033[37m"
    NORMAL="\033[0;39m"
    
    echo -e  $RED INITIALIZING TORRENT SCRIPT SIT TIGHT... 
    
    ls > list.txt
    
    sed -i '/list.txt/d' ./list.txt
    sed -i '/script.sh/d' ./list.txt
    
    for filename in $(cat list.txt); do
            echo -e $YELLOW STARTING $filename TORRENT HASH
        echo -e $WHITE
        date
        mktorrent -p -l 24 -a https://tracker.1/announce -o $filename.1.torrent "$filename" > /dev/null 2>&1
            echo -e $YELLOW PRIVATE HD $filename TORRENT HASHED
        echo -e $WHITE
        date
        mktorrent -p -l 24 -a https://tracker.2 -o $filename.2.torrent "$filename" > /dev/null 2>&1
            echo -e $YELLOW TORRENT LEECH $filename TORRENT HASHED
        echo -e $WHITE
        date
        mktorrent -p -l 24 -a https://tracker 3 -o $filename.3.torrent "$filename" > /dev/null 2>&1
            echo -e $YELLOW TORRENT DATABASE $filename TORRENT HASHED
        echo -e $WHITE
        date
        cd $filename
            ls > list.txt
            sed -i '/list.txt/d' ./list.txt
            line=$(head -n 1 list.txt)
            mediainfo $line > ./../$line.txt
        echo -e  $CYAN MEDIAINFO GENERATED
        ffmpeg -nostats -loglevel 0 -ss 00:02:45 -i $line -vframes 1 -q:v 2 ./../$line.1.jpg
            ffmpeg -nostats -loglevel 0 -ss 00:04:45 -i $line -vframes 1 -q:v 2 ./../$line.2.jpg
            ffmpeg -nostats -loglevel 0 -ss 00:06:45 -i $line -vframes 1 -q:v 2 ./../$line.3.jpg
            echo -e  $BLUE 3/10 THUMBNAILS FOR $line GENERATED
        ffmpeg -nostats -loglevel 0 -ss 00:08:45 -i $line -vframes 1 -q:v 2 ./../$line.4.jpg
            ffmpeg -nostats -loglevel 0 -ss 00:10:45 -i $line -vframes 1 -q:v 2 ./../$line.5.jpg
            ffmpeg -nostats -loglevel 0 -ss 00:12:45 -i $line -vframes 1 -q:v 2 ./../$line.6.jpg
            sleep 5
        echo -e  $PINK 6/10 THUMBNAILS FOR $line GENERATED
        ffmpeg -nostats -loglevel 0 -ss 00:14:45 -i $line -vframes 1 -q:v 2 ./../$line.7.jpg
            ffmpeg -nostats -loglevel 0 -ss 00:16:45 -i $line -vframes 1 -q:v 2 ./../$line.8.jpg
            ffmpeg -nostats -loglevel 0 -ss 00:18:45 -i $line -vframes 1 -q:v 2 ./../$line.9.jpg
            sleep 5
        echo -e  $BLUE 9/10 THUMBNAILS FOR $line GENERATED
        ffmpeg -nostats -loglevel 0 -ss 00:20:45 -i $line -vframes 1 -q:v 2 ./../$line.10.jpg
            sleep 5
        echo -e  $PINK FINISHINED GENERATING THUMBNAILS FOR $line
        cd ..
            sleep 5
        echo -e  $GREEN CLEANUP STARTED
        mkdir $filename.files
            cp *$line*.jpg ./$filename.files
            cp *$line.txt ./$filename.files
            cp $filename*.torrent ./$filename.files
            rm *$line*.jpg *$line.txt $filename*.torrent
        sleep 5
        echo -e  $GREEN CLEANUP DONE
        sleep 5
    done
    
    rm **/*list.txt
    rm list.txt
    echo -e $WHITE
    date
    echo -e  $RED TORRENT SCRIPT SUCCESSFULLY EXECUTED
    echo -e  $NORMAL

因此,此循环会生成目录的 torrent,生成 mediainfo.txt,从第一个 mkv 生成 10 个缩略图。最后生成 directory.files 目录并将生成的文件移入其中。最后清理多余的文件。

解释: 设置要与 echo -e 一起使用的颜色变量

    BLACK="\033[30m"
    RED="\033[31m"
    GREEN="\033[32m"
    YELLOW="\033[33m"
    BLUE="\033[34m"
    PINK="\033[35m"
    CYAN="\033[36m"
    WHITE="\033[37m"
    NORMAL="\033[0;39m"

使用 sed 列出起始目录的内容并删除多余的行

    ls > list.txt

    sed -i '/list.txt/d' ./list.txt
    sed -i '/script.sh/d' ./list.txt

使用 cat 从 list.txt 开始循环并设置 $filename 变量

for filename in $(cat list.txt); do

运行 mktorrent 命令将输出发送到 null,以摆脱 N 次出现的烦人的版权横幅。

mktorrent -p -l 24 -a https://tracker 3 -o $filename.3.torrent "$filename" > /dev/null 2>&1

CD 向下一级创建另一个内容列表,然后 sed 设置一个新变量 $line,该变量使用新列表的第一行。

        cd $filename
        ls > list.txt
        sed -i '/list.txt/d' ./list.txt
        line=$(head -n 1 list.txt)

使用新变量生成第一个 mkv 文件的媒体信息和缩略图

mediainfo $line > ./../$line.txt
echo -e  $CYAN MEDIAINFO GENERATED
ffmpeg -nostats -loglevel 0 -ss 00:02:45 -i $line -vframes 1 -q:v 2 ./../$line.1.jpg

cd 返回一个目录 mkdir $filename.suffix 并在结束循环之前将生成的文件移动到该目录中

      cd ..
            mkdir $filename.files
            cp *$line*.jpg ./$filename.files
            cp *$line.txt ./$filename.files
            cp $filename*.torrent ./$filename.files
            rm *$line*.jpg *$line.txt $filename*.torrent
done
     

清理 list.txt 文件

 rm **/*list.txt
    rm list.txt

相关内容