我想复制目录中的所有文件,但特定子目录中的某些文件除外。我注意到该cp
命令没有该--exclude
选项。那么,我该如何实现呢?
20 回答
rsync
快速简单:
rsync -av --progress sourcefolder /destinationfolder --exclude thefoldertoexclude
您可以--exclude
多次使用。
rsync -av --progress sourcefolder /destinationfolder --exclude thefoldertoexclude --exclude anotherfoldertoexclude
请注意,选项thefoldertoexclude
后的 dir--exclude
是相对于 的sourcefolder
,即sourcefolder/thefoldertoexclude
.
您也可以添加-n
试运行以查看在执行实际操作之前将复制的内容,如果一切正常,请-n
从命令行中删除。
好吧,如果每个 unix-ish 文件实用程序(如 cp、mv、rm、tar、rsync、scp ......)都必须排除某些文件名模式,那么就会发生巨大的重复工作。相反,这些事情可以作为globbing的一部分来完成,即通过你的 shell。
重击
man 1 bash
, / extglob。
例子:
$ shopt -s extglob $ 回声图像/* images/004.bmp images/033.jpg images/1276338351183.jpg images/2252.png $ echo images/!(*.jpg) 图像/004.bmp 图像/2252.png
所以你只需在里面放一个模式!()
,它就会否定匹配。该模式可以任意复杂,从枚举单个路径(如 Vanwaril 在另一个答案中所示)开始!(filename1|path2|etc3)
,到带有星号和字符类的类似正则表达式的东西。有关详细信息,请参阅手册页。
zsh
man 1 zshexpn
,/ 文件名生成。
您可以执行setopt KSH_GLOB
和使用类似 bash 的模式。或者,
% setopt EXTENDED_GLOB % 回声图像/* images/004.bmp images/033.jpg images/1276338351183.jpg images/2252.png % 回显图像/*~*.jpg 图像/004.bmp 图像/2252.png
所以x~y
匹配模式x
,但不包括模式y
。再一次,有关完整的详细信息,请参阅联机帮助页。
鱼新!
cp (string match -v '*.excluded.names' -- srcdir/*) destdir
奖金专业提示
键入cp *
,点击CtrlX*,然后看看会发生什么。我保证这没有害处
为什么rsync
在可以做到的时候使用:
find . -type f -not -iname '*/not-from-here/*' -exec cp '{}' '/dest/{}' ';'
这假设目标目录结构与源目录结构相同。
cp -r `ls -A | grep -v "c"` $HOME/
我找到的最简单的方法是,您只需在括号中添加文件和文件夹的名称即可复制所有文件(不包括文件和文件夹):
shopt -s extglob
cp -r !(Filename1 | FoldernameX | Filename2) Dest/
它是相对于源目录的。
这将排除目录source/.git
被复制。
rsync -r --exclude '.git' source target
扩展mvds 的评论,这对我有用
cd dotfiles
tar -c --exclude .git --exclude README . | tar -x -C ~/dotfiles2
rsync
rsync -r --verbose --exclude 'exclude_pattern' ./* /to/where/
并首先尝试使用 -n 选项来查看将要复制的内容
rsync
实际上是相当棘手的。必须进行多次测试才能使其正常工作。
假设您要复制/var/www/html
到但可能由于其大小/var/www/dev
而需要排除目录。 /var/www/html/site/video/
命令将是:
rsync -av --exclude 'sites/video' /var/www/html/ /var/www/dev
一些警告:
- 需要源中的最后一个斜杠
/
,否则它还会复制源目录而不是其内容并变为/var/www/dev/html/xxxx
,这可能不是您想要的。 --exclude
路径直接相对于源。即使您放置完整的绝对路径,它也不起作用。-v
用于详细,-a
用于存档模式,这意味着您想要递归并想要保留几乎所有内容。
cp -rv `ls -A | grep -vE "dirToExclude|targetDir"` targetDir
编辑:忘记排除目标路径(否则它会递归复制)。
我假设您使用的是 bash 或 dash。这行得通吗?
shopt -s extglob # sets extended pattern matching options in the bash shell
cp $(ls -laR !(subdir/file1|file2|subdir2/file3)) destination
执行 ls 排除您不想要的文件,并将其用作 cp 的第一个参数
另一个更简单的选择是安装和使用具有 --exclude-dir 选项的 rsync,它可以用于本地和远程文件。
只需将其临时移动到隐藏目录中(如果需要,可以在之后重命名)。
mkdir .hiddendir
cp * .hiddendir -R
mv .hiddendir realdirname
这是对 Linus Kleen 答案的修改。他的回答对我不起作用,因为会有 . 添加在 cp 不喜欢的文件路径前面(路径看起来像 source/.destination/file)。
这个命令对我有用:
find . -type f -not -path '*/exlude-path/*' -exec cp --parents '{}' '/destination/' \;
--parents 命令保留目录结构。
cp -r `ls -A | grep -v "Excluded_File_or_folder"` ../$target_location -v
mv tobecopied/tobeexcluded .
cp -r tobecopied dest/
mv tobeexcluded tobecopied/
我使用“do while”循环来读取 find 命令的输出。在此示例中,我匹配(而不是排除)某些模式,因为我想要的模式匹配数量比我不想要的要少。您可以在标志-not
前使用 a 来反转逻辑:-iname
find . -type f -iname "*.flac" -o -print0 -iname "*.mp3" -print0 -o -iname "*.wav" -print0 -o -iname "*.aac" -print0 -o -iname "*.wma" -print0 | while read -d $'\0' file; do cp -ruv "$file" "/media/wd/network_sync/music/$file"; done
我使用上面的方法来复制我的服务器上的所有音乐类型文件,这些文件比我安装在的 Western Digital TV Live Hub 上的文件更新/media/wd
。我使用上面是因为我有很多 DVD 文件、mpeg 等要排除,并且由于某种原因 rsync 看起来像是在复制,但是在我查看 wd 设备之后,尽管没有文件,但文件不存在使用此命令进行 rsync 期间的错误:
rsync -av --progress --exclude=*.VOB --exclude=*.avi --exclude=*.mkv --exclude=*.ts --exclude=*.mpg --exclude=*.iso --exclude=*ar --exclude=*.vob --exclude=*.BUP --exclude=*.cdi --exclude=*.ISO --exclude=*.shn --exclude=*.MPG --exclude=*.AVI --exclude=*.DAT --exclude=*.img --exclude=*.nrg --exclude=*.cdr --exclude=*.bin --exclude=*.MOV --exclude=*.goutputs* --exclude=*.flv --exclude=*.mov --exclude=*.m2ts --exclude=*.cdg --exclude=*.IFO --exclude=*.asf --exclude=*.ite /media/2TB\ Data/data/music/* /media/wd/network_sync/music/
ls -I "filename1" -I "filename2" | xargs cp -rf -t destdir
第一部分是ls
所有文件,但使用 flag 隐藏特定文件-I
。的输出ls
用作第二部分的标准输入。从标准输入xargs
构建和执行命令。cp -rf -t destdir
该标志-r
表示递归复制目录,-f
表示强制复制文件,这将覆盖 中的文件destdir
,-t
指定目标目录复制到。
晚了10年。归功于莱纳斯·克莱恩。
我讨厌rsync
!;) 那么为什么不使用find
andcp
呢?并且通过这个答案也mkdir
可以创建一个不存在的文件夹结构。
cd /source_folder/ && find . -type d -not -path '*/not-from-here/*' -print -exec mkdir -p '/destination_folder/{}' \;
cd /source_folder/ && find . -type f -not -path '*/not-from-here/*' -print -exec cp -au '{}' '/destination_folder/{}' \;
看起来cd
ì 有必要将相对路径与find
.
mkdir -p
将创建所有子文件夹,并且当文件夹已经存在时不会抱怨。
豪斯滕我们有下一个问题。当有人创建一个中间有一个新文件的新文件夹时会发生什么?确切地说:这些新文件将失败。(解决方案:再次运行它!:)) 将所有内容放在一个find
命令中的解决方案似乎很困难。
2022 年 1 月更新:
这是最简单的方法(并不复杂)。
首先,制作“temp”文件夹:
mkdir temp
其次,将原始文件夹中的所有文件复制到“temp”文件夹:
“-R”标志可以复制包括“符号链接”在内的所有文件
cp -R originalFolder/. temp/
第三,从“temp”文件夹中删除“myFolder”:
rm temp/myFolder
最后,将所有文件从“temp”文件夹复制到您的目标文件夹:
cp -R temp/. destinationFolder/
此外,这是没有“temp”文件夹的最短方法:
cp -R originalFolder/!(myFolder) destinationFolder/