我遇到过这种情况,我想在使用命令时排除一个目录mv
。我看到了这个示例,其中的语法是!(exclude_dir)
,但是当我设置一个场景来测试它时,我得到了我不完全理解的结果。
现在我创建了三个文件夹:f1
、f2
和f3
。现在我这样使用命令:
mv -t f3/ !(f1) f2
这会产生这个错误:
mv: cannot move 'f3' to a subdirectory of itself, 'f3/f3'
mv: cannot stat 'f2': No such file or directory
现在有趣的是文件夹的结构现在是:
.
├── f1
└── f3
└── f2
3 directories, 0 files
它按我的要求运行,但为什么会出现错误消息?显然我没有正确使用该命令。
答案1
这与 无关mv
,但是一个bash
功能,引用man bash
:
如果外接球shell 选项是使用购物内置,可识别多个扩展模式匹配运算符。在以下描述中,模式列表是由 | 分隔的一个或多个模式的列表。复合模式可使用以下一个或多个子模式形成:
!(模式列表)
匹配除给定模式之外的任意内容
!(f1)
与您的示例相匹配f2 f3
,因此您实际上正在执行以下操作:
mv -t f3/ f2 f3 f2
然后,它成功移动f2
到f3
,在尝试移动f3
到自身时引发第一个错误,并在再次尝试移动f2
到时引发第二个错误f3
,因为它已经被移动并且不再位于当前目录中。
为了实现你的目标你应该这样做:
mv -t f3/ !(f[13]) # or !(f1|f3)
此表达式匹配除f1
和 之外的所有内容f3
。
这也适用于*
、?
和[…]
:
$ ls
e1 e2 e3 f1 f2 f3
$ ls !(e*|?[12])
f3
答案2
!(f1)
是一个扩展全局表达式,因此(假设extglob
设置了 shell 选项)它会扩展为列表(不)匹配的文件。换句话说,如果您的目录最初包含f1
,f2
,f3
那么
mv -t f3/ !(f1) f2
展开为
mv -t f3/ f2 f3 f2
第一个错误应该是显而易见的;第二个错误是因为它尝试移动f2
两次——但第二次失败了。
答案3
或者你也可以使用rsync
:
rsync -arv --exclude=.ccache --exclude=build /home/ben /media/ben/thumbdrive/
答案4
如果你正在寻找一种备份当前文件的方法,将移动命令拆分为复制并删除。 例如:
# Allow wildcard and hidden files search
shopt -s extglob dotglob
# Make a new directory (skip if exists)
mkdir -p BACKUP
# Copy all files to BACKUP (-a to keep attributes, -f to overwrite existing)
cp -af !(BACKUP) BACKUP/
# Remove all files except BACKUP (and hidden files starting with ".keep")
rm -rf !(BACKUP|.keep*)