答案1
和zsh
:
set -o extendedglob
cp -- ^*<->*(D^/) /path/to/destination/
或者cp -- ^*[0-9]*(D^/) destination/
,匹配一个或多个 ASCII 十进制数字的任何序列(一种未设置边界<->
的形式)。<x-y>
(^
作为否定运算符,D
包括隐藏文件,^/
也排除目录类型的文件,无论如何,如果没有 // ,这些文件将拒绝cp
复制)。-r
-R
-a
bash
与:相同
shopt -s extglob failglob dotglob
cp -- !(*[0123456789]*) /path/to/destination/
!(x)
(来自 ksh,需要extglob
在读取使用它的代码时进行设置)相当于 zsh 的^x
,dotglob
作为限定符的相当于D
,bash 没有相当于 的^/
。如果没有,如果没有匹配的文件,failglob
则可以复制字面调用的文件。!(*[0123456789]*)
使用 glob 的 POSIX 版本总是非常难以实现,因为没有 glob 限定符或等效的nullglob
, failglob
(zsh 中的默认行为)或globdot
/ dotglob
/D
限定符,也没有 ksh 风格或 zsh 风格的否定运算符:
set -- [*] *
[ "$1$2" = '[*]*' ] && shift
shift
set -- .[*] .* "$@"
[ "$1$2" = '.[*].*' ] && shift
shift
for file do
case "$file" in
(*[0123456789]* | . | ..) ;;
(*) [ -d "$file" ] && [ ! -L "$file" ] || set -- "$@" "$file";;
esac
shift
done
[ "$#" -gt 0 ] && echo cp -- "$@" /path/to/destination/
但你可以使用find
:
LC_ALL=C find . ! -name . -prune ! -name '*[0-9]*' ! -type d \
-exec sh -c 'exec cp "$@" /path/to/destination/' sh {} +
LC_ALL=C
解决这样的事实:-name
s*
可能无法匹配无法在用户区域设置中解码为文本的字节序列。在C
语言环境中,[0-9]
和[0123456789]
也是等效的。然而,这意味着这可能会排除以 BIG5 或 GB18030 等字符集编码的文件名,其中某些字符的编码包含 ASCII 数字的字节值。在中国和附属国之外不太可能。
zsh
应该能够使用不完全由文本组成的字符集或文件名来处理语言环境和文件名。bash
如果文件名无法完全解码,它也会切换到按字节匹配,这可能会在某些极端情况下导致令人惊讶的结果,包括与上述 BIG5/GB18030 相同的情况。
zsh
'[0-9]
总是与 相同[0123456789]
,bash 在 C/POSIX 语言环境之外很少如此。
你的:
cp [!0-9] *[!0-9] *[!0-9] 目的地
不起作用,因为那是:
[!0-9]
: 文件名是除 0 和 9 之间排序之外的单个字符。如果没有这样的单字母字符,则在bash
不使用failglob
或nullglob
启用的情况下,保留的[!0-9]
文件名是包含 2 位数字的文件名。*[!0-9]
:以 0 到 9 之间排序以外的字符结尾的文件名。1234567X
例如,So 会匹配。*[!0-9]
同样,我猜这是一个错字,但如果你的意思是[!0-9]*
那就匹配X12345
,如果你的意思是*[!0-9]*
,那么就会匹配1234X5678
。
如果您的意思是 regexp 的等价物^[^0-9]*$
,或者更好^[^0123456789]*$
,其中*
regexp 意味着 0 或更多前面的事情而不是 0 个或多个人物在 glob 中,那么这将是*([!0123456789])
Korn 风格的扩展 glob(bash with 也支持extglob
)或[^0-9]#
zsh 扩展 glob。另请参阅+([!0123456789])
(ksh) 和[^0-9]##
(zsh) 以了解 ERE 的等效项+
(此处不会产生任何影响,因为文件名无论如何都不能为空)。
另请注意,当您忘记--
标记选项结尾时,任何以 开头的文件名-
都会被视为选项cp
。例如,对于名为-rt..
GNU 的文件cp
,最终会复制所有其他文件并/path/to/destination
递归到父目录!
答案2
POSIX 方法可能是保存包含 0 到 9 之间字符排序的文件(使用[0-9]
; 或带 ; 的十进制数字[[:digit:]]
或仅带 0123456789 的数字[0123456789]
),复制其余部分,然后恢复保存的集:
mkdir ".save.$$" &&
mv ./*[0-9]* ".save.$$/"
cp ./* /target/directory/ &&
mv ".save.$$"/* . &&
rmdir ".save.$$"
这将故意不复制点文件。如果您想要包含这些内容,您将需要一个更复杂的解决方案。
答案3
好吧,我不知道这是否是最好的方法,但这有效:
cp $(ls --ignore="*[0-9]*") YOUR_DIR
编辑:
(阅读@StéphaneChazelas 的评论,为什么你不应该使用第一个命令)
这可能效果更好:
find . -type f -maxdepth 1 -not -regex '.*[0-9].*' -exec cp {} move \;
答案4
使用乐(以前称为 Perl_6)
raku -e 'for dir(test => none / \d /, ".", "..") { copy $_, $_ ~ ".bak" };'
Raku 是 Perl 编程语言家族中的一种语言。上面的 Raku 代码.bak
在同一目录中创建一个备份文件。它使用一个有趣的运算符类/类型,称为交界处。 Raku 语言中有四种可用的连接类型:none
、one
和any
。all
~$ ls
persons.txt places.txt thx1138.txt
~$ perl6 -e 'for dir(test => none / \d /, ".", "..") { copy $_, $_ ~ ".bak" };'
~$ ls
persons.txt persons.txt.bak places.txt places.txt.bak thx1138.txt
上面(特别是)none
给出了一个 Junction 的 3 项列表,其中删除了:
- 包含数字的文件名
\d
(使用正则表达式匹配器), - 点
"."
目录, - 点对点
".."
目录。
一旦选择了正确的文件名,块内的$_
(这些文件)就会被copy
复制到一个备份文件中,该文件由文件名后跟.bak
(单个波形符~
用于连接 Raku 中的字符串)组成。
备份/复制到不同的目录:
Raku 有多个选项用于将文件复制和/或备份到不同的目录。知道 apath
由 adirname
和组成basename
。在某些时候,您可能想要获取absolute
路径而不是relative
路径(并resolve
对其进行-ing)。另外,您可以使用 上升路径,并使用(这是 的同义词)parent
将目录添加到路径中。请参阅下面的链接“输入/输出权威指南”以获取提示。add
child
这是一种方法(复制到备份/Tmp
目录,原始文件名保持不变):
~$ raku -e 'my $Cwd = $*CWD; \
mkdir(my $Tmp = $Cwd.parent.add: "/Tmp/"); \
for $Cwd.dir(test => none / \d /, ".", "..") {
copy $_, IO::Path($Tmp ~ $_.basename)
};'
~$ cd ../Tmp
~$ ls
persons.txt places.txt
https://docs.raku.org/type/IO/Path
https://docs.raku.org/language/io-guide#Input/Output_the_definitive_guide