简体   繁体   English

如何在子目录中查找匹配模式和替换模式的所有文件

[英]How to find all files in subdirectories that match pattern and replace pattern

I am attempting to move some video files of mine into new subdirectories while also renaming them on my Unraid system.我试图将我的一些视频文件移动到新的子目录中,同时也在我的 Unraid 系统上重命名它们。 The files all follow a similar naming convention:这些文件都遵循类似的命名约定:

featurette name-featurette.mkv

I would like to move these files from their current directory to a subdirectory and rename them like this:我想将这些文件从它们的当前目录移动到一个子目录并像这样重命名它们:

featurettes/featurette name.mkv 

I am able to create the directories and relocate the files using find and execdir:我能够使用 find 和 execdir 创建目录并重新定位文件:

find . -type f -name *-featurette.mkv -maxdepth 2 -execdir mkdir ./featurettes/ \;
find . -type f -name *-featurette.mkv -maxdepth 2 -execdir mv {} ./featurettes/ \;

I am struggling with the renaming piece.我正在为重命名作品而苦苦挣扎。 I've tried the rename command but am unable to get it to work within the featurettes directory, let alone from two directories above, which is where I'd like to execute the command.我已经尝试了重命名命令,但无法让它在 featurettes 目录中工作,更不用说从上面的两个目录中工作了,这是我想要执行命令的地方。 I've tried the following command within the featurettes directory:我在 featurettes 目录中尝试了以下命令:

rename \-featurette.mkv .mkv *

However I get the error:但是我收到错误:

invalid option -- 'f'

I thought by escaping the dash I could avoid that issue, but it doesn't appear to work.我认为通过逃避破折号我可以避免这个问题,但它似乎不起作用。 Any advice on how to remove this pattern from all files within subdirectories matching it would be very much appreciated.关于如何从匹配它的子目录中的所有文件中删除此模式的任何建议将不胜感激。

From man rename you see this command gets options and 3 positional parameters:man rename您可以看到此命令获取选项和 3 个位置参数:

SYNOPSIS rename [options] expression replacement file...大纲重命名 [选项] 表达式替换文件...

So in your case the first parameter is being interpreted as an option.所以在你的情况下,第一个参数被解释为一个选项。 You may use this syntax:您可以使用以下语法:

rename -- '-featurette' '' *-featurette.mkv

to rename the files.重命名文件。 -- indicates that any options are over and what follows are only positional parameters. --表示任何选项都结束了,后面的只是位置参数。


Totally, to copy the files with one mv process and rename them:总而言之,用一个mv进程复制文件并重命名它们:

mkdir -p target/dir
find . -maxdepth 2 -type f -name "*-featurette.mkv" -exec mv -t target/dir {} +
cd target/dir && rename -- '-featurette' '' *-featurette.mkv

If you want to rename many files located into different subdirectories, you can use this syntax:如果要重命名位于不同子目录中的许多文件,可以使用以下语法:

find . -name "*-featurette.mkv" -print0 | xargs -r0 rename -- '-featurette' ''  
find . \
  -maxdepth 2 \
  -type f \
  -name '*-featurette.mkv' \
  -execdir sh -c '
echo mkdir -p ./featurettes/
echo mv -- "$@" ./featurettes/
' _ {} \+

Issue with your implementations I fixed or improved:我修复或改进的实现问题:

  • -maxdepth 2 must precede -type f -maxdepth 2必须在-type f之前
  • -name '*-featurette.mkv' must have the pattern quoted to prevent the shell to expand globb it. -name '*-featurette.mkv'必须引用模式以防止 shell 扩展它。
  • -execdir is best used with an inline shell, so it can also process multiple arguments from the same directory -execdir最好与内联 shell 一起使用,因此它也可以处理来自同一目录的多个参数

Also keep in mind that while running a command with -execdir , find will cd to that directory.还要记住,在使用-execdir运行命令时, findcd到该目录。 It means that mv -- "$@" ./featurettes/' will move files into the ./featurettes/' directory relative to were -execdir has just cd .这意味着mv -- "$@" ./featurettes/'将文件移动到./featurettes/'相对目录是-execdir刚刚cd

Version which also rename files while moving:移动时也重命名文件的版本:

( has no echo dry-run protection, so use only if you are sure it does what you want ) (没有echo干运行保护,因此只有在您确定它可以满足您的需求时才使用)

#!/usr/bin/env sh

find . \
  -maxdepth 2 \
  -depth \
  -name '*-featurette.mkv' \
  -type f \
  -execdir sh -c '
mkdir -p featurettes
for arg
do
  basename=${arg##*/}
  mv -- "$basename" "./featurettes/${basename%-featurette.mkv}.mkv"
done
' _ {} +

You can use Bash's shell parameter expansion feature to get the part of the file name, for example:您可以使用 Bash 的 shell 参数扩展功能来获取文件名的部分,例如:

$> filename=name-featurette.mkv
$> echo ${filename%-*} #To print first part before '-'
name
$> echo ${filename##*.} #To get the extension
mkv
$> echo ${filename#*-} #To print the part after '-' with extension
featurette.mkv

With this and slightly modifying your find command, you should be able to move+rename your files:有了这个并稍微修改你的 find 命令,你应该能够移动+重命名你的文件:

find . -type f -name '*-featurette.mkv' -maxdepth 2 -execdir sh -c 'f="{}"; mv -- "$f" ./featurettes/"${f%-*}.mkv"' \;

In fact you should be able to combine both the find command into one to create_dir, move and rename file.事实上,您应该能够将 find 命令合二为一来创建目录、移动和重命名文件。

find . -type f -name '*-featurette.mkv' -maxdepth 2 -execdir sh -c 'f="{}"; mkdir ./featurettes; mv -- "$f" ./featurettes/"${f%-*}.mkv"' \;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM