我有一个很大的图片文件夹(成千上万个),并且我有一长串文件(按确切的文件名),需要将其复制到另一个文件夹中。我想知道是否有一种方法可以从该文件夹中按名称选择几个特定文件,然后使用终端将它们复制到另一个文件夹中,而不必分别复制它们?

评论

Fyi,用于复制特定文件夹,请使用:cp -rp / copying / from / {folder1 /,folder2 /,folder3 /} path / to / folder,其中p用于复制文件夹权限。

#1 楼

只需从命令行一次复制多个文件即可。
有几种方法可以实现此目的。我看到的最简单的方法是使用以下命令。
cp /home/usr/dir/{file1,file2,file3,file4} /home/usr/destination/

语法使用cp命令,后跟所需文件所在目录的路径,所有要复制的文件都放在方括号中并以逗号分隔。
请确保注意文件之间没有空格。命令的最后一部分/home/usr/destination/是您要将文件复制到的目录。
或者如果所有文件的前缀相同但结尾不同,则可以执行以下操作:
cp /home/usr/dir/file{1..4} ./

将file1,file2,file3和file4复制到哪里。
从您如何表达问题的角度来看,我相信这是您正在寻找的东西,但听起来您可能正在寻找要从中读取的命令文件列表,然后将所有文件复制到某个目录。如果是这种情况,请告诉我,我将编辑我的答案。
使用python处理重复项
所以我写了一个小python脚本,我相信应该可以完成工作。但是,我不确定您是否精通python(如果完全精通),因此我将尽力解释如何使用此脚本,并请根据需要询问尽可能多的问题。
< pre class =“ lang-py prettyprint-override”> import os,sys,shutil ### copies a list of files from source. handles duplicates. def rename(file_name, dst, num=1): #splits file name to add number distinction (file_prefix, exstension) = os.path.splitext(file_name) renamed = "%s(%d)%s" % (file_prefix,num,exstension) #checks if renamed file exists. Renames file if it does exist. if os.path.exists(dst + renamed): return rename(file_name, dst, num + 1) else: return renamed def copy_files(src,dst,file_list): for files in file_list: src_file_path = src + files dst_file_path = dst + files if os.path.exists(dst_file_path): new_file_name = rename(files, dst) dst_file_path = dst + new_file_name print "Copying: " + dst_file_path try: shutil.copyfile(src_file_path,dst_file_path) except IOError: print src_file_path + " does not exist" raw_input("Please, press enter to continue.") def read_file(file_name): f = open(file_name) #reads each line of file (f), strips out extra whitespace and #returns list with each line of the file being an element of the list content = [x.strip() for x in f.readlines()] f.close() return content src = sys.argv[1] dst = sys.argv[2] file_with_list = sys.argv[3] copy_files(src,dst,read_file(file_with_list))
此脚本应该相对简单易用。首先,将上述代码复制到程序gedit(应在Ubuntu中预安装)或任何其他文本编辑器中。
完成后,将文件另存为move.py在您的主目录中(可以将其保存为为了便于说明,任何目录都可以只使用主目录),也可以将文件所在的目录添加到PATH中。然后从终端将cd移至您的主目录(或保存了move.py的任何目录),并键入以下命令:
python move.py /path/to/src/ /path/to/dst/ file.txt

这应该将源目录中列出的所有文件复制到目标目录,并带有重复格式为pic(1).jpg,pic(2).jpg等的副本。
file.txt应该是文件,该文件列出了您要复制的所有图片,并且每个条目都在其单独的行上。
此脚本绝不会影响源目录,但是请确保输入正确的源目录和目标目录路径最糟糕的情况是将文件复制到错误的目录。
注意事项

此脚本假定所有原始图片都在同一目录中。如果您还希望它检查子目录,则该脚本
将需要进行修改。
如果您不小心键入了一个文件名,该脚本将吐出错误
“文件不存在”,并提示您“按Enter”继续,脚本将继续复制列表的其余部分。
请不要忘记源
目录路径和路径上的末尾/。目标目录。否则脚本
会向您吐一个错误。


评论


谢谢,这解决了我的大部分问题,但是,某些文件出现在列表中两次或更多次,如何使它自动重命名这些重复项? (是的,我需要重复做我的工作。)

–图片太多的人
13年8月1日在6:09

是来自不同子文件夹的重复项,还是带有诸如file.jpg和file(1).jpg之类的标签?否则,我不确定您的文件是否相同。为了以某种方式回答您的问题,我认为您将无法找到一种简单的衬纸,可以自动为您重命名重复项。我认为必须编写bash或其他类型的脚本才能获得这种功能。但是,我看到了一些非常荒谬的单行命令,因此也许某些Linux向导可能会出现并提供答案。

–布莱恩(Bryan)
13年8月1日在6:17

我最初每个文件只有一个,但是文件名在列表中两次或多次。尝试将文件放置在新文件夹中并且已经存在该名称的文件时,我或多或少需要执行该操作,我需要在该文件名的末尾添加(2)左右并放置它。

–图片太多的人
13年8月1日在6:22

我只想建议强调一下有关要复制的文件列表中没有空格的部分。如果在文件{foo,bar,..}之间有空格,该命令将不起作用。

–弗兰克斯·桑德斯
18年11月19日在13:00

对于那些寻求进一步捷径的用户,您可以使用命令替换来代替文件的绝对路径,即cp $(pwd)/ {file1,file2} / path / to / dst /或cp $(pwd)/ {file1,file2} $ {pwd)/ {renamed1,renamed2}等。

–baelx
19年1月17日,0:21

#2 楼

也许我缺少您的问题的详细信息,但给出的答案似乎过多。如果要命令行解决方案而不是脚本,为什么不这样做:

cd /path/to/src/
cp -t /path/to/dst/ file1 file2 file3 ...


这样操作的好处是可以制表完整文件名

评论


这将在macOS Sierra中返回“非法选项--t”

–geoyws
16-10-20在7:01



好的答案,简单得多。 @geoyws也许是苹果版本所没有的POSIX或GNU。在Debian Linux或带有MSYS2的Windows上,它对我来说工作正常。

– underscore_d
16-10-22在14:38



好建议!在Arch Linux中工作。

– Edu Ruiz
17 Mar 31 '13:31



brew install coreutils之后,您可以获取带有g前缀的常规gnu东西。那就是gcp -t ....

– T.Chmelevskij
17-10-22在10:16

Mac OS使用cp的BSD版本,尤其是OpenBSD和FreeBSD都没有该选项,因此是的-这是GNU cp特定的。 POSIX标准也未指定。由于这是Ubuntu特定站点,因此可以接受,但是对于在OS之间移植脚本,最好坚持使用POSIX标准

– Sergiy Kolodyazhnyy
18年5月26日在7:36

#3 楼

这是一个纯bash解决方案。它将从输入文件中读取文件名(每行一个)并复制每个文件名,重命名重复项。

 #!/usr/bin/env bash

## The destination folder where your files will
## be copied to.
dest="bar";

## For each file path in your input file
while read path; do 
    ## $target is the name of the file, removing the path. 
    ## For example, given /foo/bar.txt, the $target will be bar.txt.
    target=$(basename "$path"); 
    ## Counter for duplicate files
    c=""; 
    ## Since $c is empty, this will check if the
    ## file exists in target.
    while [[ -e "$dest"/"$target"$c ]]; do
        echo "$target exists"; 
        ## If the target exists, add 1 to the value of $c
        ## and check if a file called $target$c (for example, bar.txt1)
        ## exists. This loop will continue until $c has a value
        ## such that there is no file called $target$c in the directory.
        let c++; 
        target="$target"$c; 
    done; 
    ## We now have everything we need, so lets copy.
    cp "$path" "$dest"/"$target"; 
done
 


将此脚本保存在$PATH的文件夹中,并用输入的路径:

auto_copy.sh < file_paths.txt


您还可以从终端作为命令运行整个程序:

 while read path; do 
   target=$(basename "$path"); 
   c=""; 
   while [[ -e bar/"$target"$c ]]; do 
    echo "$target exists"; 
    let c++; 
    target="$target"$c; 
   done; 
   cp "$file" bar/"$target"; 
done < file_names;
 


#4 楼

根据问题的描述,我的理解是:


有一个文件列表,大概是文本文件input.txt

该列表仅包含文件名
这些文件名存在一个特定的目录。

因此,可以使用以下命令:

xargs -I % --arg-file=input.txt cp  /path/to/origin_dir/%  /path/to/destination


说明:



-I %指定要在命令中使用的当前处理文件的符号

--arg-file=input.txt指定将参数从input.txt用作命令


cp /path/to/origin_dir/% /path/to/destination/将执行cp命令,并将/path/to/origin_dir/%替换为/path/to/origin_dir/和当前处理的文件名。

实际示例:

$ cat input.txt
file2.txt
file1.txt
file3.txt
$ ls ./docs
file1.txt  file2.txt  file3.txt
$ xargs -I % --arg-file=input.txt cp ./docs/% ./docs_destination/
$ ls ./docs_destination/
file1.txt  file2.txt  file3.txt


#5 楼

遇到过几次之后,我的解决方案是将所有内容cp放到一个文件夹中的小脚本,因此看起来就像我想要的存档文件(文件夹和所有文件夹),然后cd <folder_to_be_zipped>zip -r ../<zip_file_name>.zip .我最终在需要的地方得到一个.zip文件。
另一种方法是使用多个zip命令,例如:
 cd <parent_of_directory> && zip -r /path/to/archive.zip directory/* && \
cd <folder_with_files> && zip /path/to/archive.zip addfile1 addfile2 addfile2;
 

样本提供:https://wpguru.co.uk/2018/12/how-to-add-files-to-an-existing-zip-archive-on-macos-and-linux/