bash 匹配模式的 grep 文件名并移动到所需的文件夹

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13928064/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 04:02:09  来源:igfitidea点击:

grep filenames matching a pattern and move to desired folder

linuxbashshellgrepmove

提问by ana

I have a list of patterns in a .txt file. [list.txt]. Foreach line in list.txt, I want to find all the files at a location which begin with the specified pattern in list.txt, and then move these files to another location. Consider an example case.

我在 .txt 文件中有一个模式列表。[列表.txt]。对于list.txt 中的每一行,我想在list.txt 中以指定模式开始的位置查找所有文件,然后将这些文件移动到另一个位置。考虑一个例子。

at ~/home/ana/folder_aI have list.txt, which looks like this...

~/home/ana/folder_a我有list.txt,看起来像这样......

list.txt

列表.txt

1abc
2def
3xyz

At this location i.e /home/ana/folder_a/, there are multiple files which are beginning with the patterns in list.txt. So, there are files like 1abc_a.txt, 1abc_c.txt, 1abc_f.txt, 2def_g.txt, 3xyz_a.txt

在这个位置,即/home/ana/folder_a/,有多个以 list.txt 中的模式开头的文件。所以,有像 1abc_a.txt, 1abc_c.txt, 1abc_f.txt, 2def_g.txt, 3xyz_a.txt 这样的文件

So what I want to achieve is this:

所以我想要实现的是:

for i in cat list.txt; do 
  ls | grep '^$i' [thats the pattern] | 
  mv [files containing the pattern] to /home/ana/folder_b/

Please note that at the other location, i.e /home/ana/folder_b/ I have already created directories, specific for each pattern.

请注意,在另一个位置,即 /home/ana/folder_b/,我已经创建了特定于每个模式的目录。

So /home/ana/folder_b/ contains subdirectories like 1abc/ , 2def/ , 3xyz/ In effect, I wish to move all the files matching pattern '1abc', '2def' and '3xyz' from /home/ana/folder_a/ to their respective sub-directories in /home/ana/folder_b/, such that /home/ana/folder_b/1abc will have 1abc_a.txt , 1abc_c.txt , and 1abc_f.txt ; /home/ana/folder_b/2def/ will have 2def_g.txt and /home/ana/folder_b/3xyz/ will have 3xyz_a.txt

所以 /home/ana/folder_b/ 包含像 1abc/ 、 2def/ 、 3xyz/ 这样的子目录 实际上,我希望从 /home/ana/folder_a/ 移动与模式 '1abc'、'2def' 和 '3xyz' 匹配的所有文件到 /home/ana/folder_b/ 中各自的子目录,这样 /home/ana/folder_b/1abc 将有 1abc_a.txt 、 1abc_c.txt 和 1abc_f.txt ;/home/ana/folder_b/2def/ 将有 2def_g.txt 和 /home/ana/folder_b/3xyz/ 将有 3xyz_a.txt

采纳答案by Thor

I think glob expansion is the way to go here:

我认为 glob 扩展是这里的方法:

while read pattern; do
  mv "${pattern}"* ../folder_b/"$pattern"
done < list.txt

Start with an echoin front of the mvcommand, and remove it when you're happy with the output.

从命令echo前面的an 开始,mv当您对输出感到满意时将其删除。

回答by Chris Seymour

Grep's -foption matches patterns from a file so you don't have to loop over each line in the file in shell:

Grep 的-f选项匹配文件中的模式,因此您不必遍历文件中的每一行shell

$ ls                              # List all files in dir, some match, some don't
1abc_a.txt 1abc_c.txt 1abc_f.txt  2def_g.txt 3xyz_a.txt file1 file2 list.txt

$ cat list.txt                    # List patterns to match against 
1abc
2def
3xyz

$ ls | grep -f list.txt           # grep for files that only match pattern
1abc_a.txt
1abc_c.txt
1abc_f.txt
2def_g.txt
3xyz_a.txt

Pipe to xargsto do the move:

管道xargs来做移动:

ls | grep -f list.txt | xargs -i -t mv {} ../folder_B
mv 1abc_a.txt ../folderB 
mv 1abc_c.txt ../folderB 
mv 1abc_f.txt ../folderB 
mv 2def_g.txt ../folderB 
mv 3xyz_a.txt ../folderB 

Edit: Realised I missed the subdirectory part of the question, @Thor's answers is the best approach for this, still I think you might find some use from this answer.

编辑:意识到我错过了问题的子目录部分,@Thor 的答案是最好的方法,但我仍然认为您可能会从这个答案中找到一些用处。

回答by nullrevolution

i'd suggest using the -execaction of findto call mvin your loop.

我建议使用在你的循环中调用的-exec动作。findmv

beginning file structure: (as you can see, i'm calling this from the parent of folder_a and folder_b)

起始文件结构:(如您所见,我从 folder_a 和 folder_b 的父级调用它)

$ find
.
./folder_a
./folder_a/1abc_a.txt
./folder_a/1abc_c.txt
./folder_a/1abc_f.txt
./folder_a/2def_g.txt
./folder_a/3xyz_a.txt
./folder_b
./folder_b/1abc
./folder_b/2def
./folder_b/3xyz
./list.txt

$ cat list.txt
1abc
2def
3xyz

command:

命令:

while read pattern
 do 
  find ./folder_a -type f -name "$pattern*" -exec mv "{}" "./folder_b/$pattern" \;
 done <list.txt

alternate command (same thing, just all on one line):

替代命令(同样的事情,只是在一行上):

while read pattern; do find ./folder_a -type f -name "$pattern*" -exec mv "{}" "./folder_b/$pattern" \;; done <list.txt

resulting file structure:

结果文件结构:

$ find
.
./folder_a
./folder_b
./folder_b/1abc
./folder_b/1abc/1abc_a.txt
./folder_b/1abc/1abc_c.txt
./folder_b/1abc/1abc_f.txt
./folder_b/2def
./folder_b/2def/2def_g.txt
./folder_b/3xyz
./folder_b/3xyz/3xyz_a.txt
./list.txt