rsync
快速简单:
rsync -av --progress sourcefolder /destinationfolder --exclude thefoldertoexclude
您可以多次使用 --exclude
。
rsync -av --progress sourcefolder /destinationfolder --exclude thefoldertoexclude --exclude anotherfoldertoexclude
请注意,--exclude
选项之后的 dir thefoldertoexclude
是相对于 sourcefolder
的,即 sourcefolder/thefoldertoexclude
。
您还可以添加 -n
进行试运行以查看在执行实际操作之前将复制的内容,如果一切正常,请从命令行中删除 -n
。
好吧,如果每个 unix-ish 文件实用程序(如 cp、mv、rm、tar、rsync、scp、...)都必须排除某些文件名模式,就会产生巨大的重复劳动。相反,这些事情可以作为 globbing 的一部分来完成,即通过您的 shell。
重击
man 1 bash
,/ extglob。
例子:
$ shopt -s extglob $ echo images/* images/004.bmp images/033.jpg images/1276338351183.jpg images/2252.png $ echo images/!(*.jpg) images/004.bmp images/2252.png
因此,您只需在 !()
中放置一个模式,它就会否定匹配。该模式可以是任意复杂的,从枚举单个路径(如 Vanwaril 在另一个答案中所示)开始:!(filename1|path2|etc3)
,到带有星号和字符类的类似正则表达式的东西。有关详细信息,请参阅手册页。
zsh
man 1 zshexpn
,/ 文件名生成。
您可以执行 setopt KSH_GLOB
并使用类似 bash 的模式。或者,
% setopt EXTENDED_GLOB % echo images/* images/004.bmp images/033.jpg images/1276338351183.jpg images/2252.png % echo images/*~*.jpg images/004.bmp images/2252.png
所以 x~y
匹配模式 x
,但排除模式 y
。再一次,有关完整的详细信息,请参阅联机帮助页。
新鱼!
fish shell 有一个 much prettier answer:
🐟 cp (string match -v '*.excluded.names' -- srcdir/*) destdir
奖金专业提示
输入 cp *
,点击 CtrlX* 看看会发生什么。 它没有害处我保证
zsh
中有效。
setopt -u extglob
。
cp
这样的文件操作实用程序如何不支持这个开箱即用的最简单直接的用例,这超出了我的理解。不过感谢您的提示!
为什么在可以执行以下操作时使用 rsync
:
find . -type f -not -iname '*/not-from-here/*' -exec cp '{}' '/dest/{}' ';'
这假设目标目录结构与源目录结构相同。
-path
参数来测试路径层次结构,而不是 -iname
find . -type f -not -path '*/not-from-here/*' -exec cp '{}' '/dest/{}' \;
rsync
?因为它可能不存在于系统中!而 find
、cp
总是在他们的位置上。或者你来自那种安装 2gigs 的东西来做简单事情的人?
cp -r `ls -A | grep -v "c"` $HOME/
# $1 = source path # $2 = destination path # $3 = filter copy_from_source_to_destination_except_filter() { cp -r $(ls -A $1 | grep -v -w $3 | awk -v path=$1 '{printf "%s/%s ", path, $1}') $2 }
cp -r "$(ls -A | grep -v "c")" $HOME/
应该可以工作。答案中的命令失败,因为 cp
对 ls -A | grep -v "c"
的输出进行操作,该输出未加引号,因此在空格处中断。 "$(…)"
与 "`…`"
相同,但更容易理解。
我找到的最简单的方法是,您只需在括号中添加文件和文件夹的名称即可复制所有文件(不包括文件和文件夹):
shopt -s extglob
cp -r !(Filename1 | FoldernameX | Filename2) Dest/
-bash: !: event not found
它是相对于源目录的。
这将排除目录 source/.git
被复制。
rsync -r --exclude '.git' source target
扩展 mvds’s comment,这对我有用
cd dotfiles
tar -c --exclude .git --exclude README . | tar -x -C ~/dotfiles2
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 用于存档模式,这意味着您想要递归并想要保留几乎所有内容。
--exclude
标志,例如:--exclude 'foo' --exclude 'bar'
cp -rv `ls -A | grep -vE "dirToExclude|targetDir"` targetDir
编辑:忘记排除目标路径(否则它会递归复制)。
rsync
rsync -r --verbose --exclude 'exclude_pattern' ./* /to/where/
并首先尝试使用 -n 选项来查看将要复制的内容
我假设您使用的是 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 的第一个参数
ls
,直接执行 cp !(file1|file1) dest
。
cp $(ls folder/!exclude_folder0|exclude_folder1)) dest
另一个更简单的选择是安装和使用具有 --exclude-dir 选项的 rsync,它可以用于本地和远程文件。
只需将其临时移动到隐藏目录中(如果需要,可以在之后重命名)。
mkdir .hiddendir
cp * .hiddendir -R
mv .hiddendir realdirname
cp
和标准 POSIX shell(如 sh
)的选项。
这是对 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
rsync
对我们不可用。下面是一个可行的替代方案。
tar -cf - --exclude='./folder' --exclude='./file.tar' ./source_directory | tar -xf - -C ./destination_directory
mv tobecopied/tobeexcluded .
cp -r tobecopied dest/
mv tobeexcluded tobecopied/
ls -I "filename1" -I "filename2" | xargs cp -rf -t destdir
第一部分 ls
所有文件,但隐藏带有标志 -I
的特定文件。 ls
的输出用作第二部分的标准输入。 xargs
从标准输入构建并执行命令 cp -rf -t destdir
。标志-r
表示递归复制目录,-f
表示强制复制文件,这将覆盖destdir
中的文件,-t
指定目标目录复制到。
晚了10年。归功于莱纳斯·克莱恩。
我讨厌rsync
! ;) 那么为什么不使用 find
和 cp
呢?并通过此答案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
命令的解决方案似乎很困难。
清理:https://unix.stackexchange.com/q/627218/239596
-not -path '*/not-from-here/*'
,它将创建目录 ./not-from-here
。可能,这不是故意的。因此,对于第一步(目录创建),您可能需要 -not -path '*/log'
。
我使用“do while”循环来读取 find 命令的输出。在此示例中,我匹配(而不是排除)某些模式,因为我想要的模式匹配数量比我不想要的要少。您可以在 -iname
标志前使用 -not
反转逻辑:
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
我使用上述方法复制了我的服务器上的所有音乐类型文件,这些文件比我安装在 /media/wd
的 Western Digital TV Live Hub 上的文件新。我之所以使用上面是因为我有很多 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/
--exclude
的简单性和强大功能thefoldertoexclude
是相对于sourcefolder
还是当前工作目录?谢谢rsync -av --progress --exclude="thefoldertoexclude" sourcefolder /destinationfolder
- 无论如何都赞成 rsync 而不是 find,因为您可以轻松地使用绝对路径作为源,而在 find 中它使用{}
更棘手目的地rsync -av --progress sourcefolder/ destinationfolder --exclude thefoldertoexclude