这个Perl如何检查一个目录是否为空工作?

时间:2022-09-01 23:09:16

I got this strange line of code today, it tells me 'empty' or 'not empty' depending on whether the CWD has any items (other than . and ..) in it.

我今天得到了这个奇怪的代码行,它告诉我'空'或'不空'取决于CWD是否有任何项目(除了。和..)。

I want to know how it works because it makes no sense to me.

我想知道它是如何工作的,因为它对我没有意义。

perl -le 'print+(q=not =)[2==(()=<.* *>)].empty'

The bit I am interested in is <.* *>. I don't understand how it gets the names of all the files in the directory.

我感兴趣的是<。* *>。我不明白它如何获取目录中所有文件的名称。

5 个解决方案

#1


It's a golfed one-liner. The -e flag means to execute the rest of the command line as the program. The -l enables automatic line-end processing.

这是一个高尔夫单线。 -e标志表示执行命令行的其余部分作为程序。 -l启用自动行结束处理。

The <.* *> portion is a glob containing two patterns to expand: .* and *.

<。* *>部分是一个包含两个扩展模式的glob:。*和*。

This portion

(q=not =)

is a list containing a single value -- the string "not". The q=...= is an alternate string delimiter, apparently used because the single-quote is being used to quote the one-liner.

是包含单个值的列表 - 字符串“not”。 q = ... =是一个替代的字符串分隔符,显然是使用的,因为单引号用于引用单行。

The [...] portion is the subscript into that list. The value of the subscript will be either 0 (the value "not ") or 1 (nothing, which prints as the empty string) depending on the result of this comparison:

[...]部分是该列表的下标。下标的值将为0(值“not”)或1(nothing,打印为空字符串),具体取决于此比较的结果:

2 == (()=<.* *>)

There's a lot happening here. The comparison tests whether or not the glob returned a list of exactly two items (assumed to be . and ..) but how it does that is tricky. The inner parentheses denote an empty list. Assigning to this list puts the glob in list context so that it returns all the files in the directory. (In scalar context it would behave like an iterator and return only one at a time.) The assignment itself is evaluated in scalar context (being on the right hand side of the comparison) and therefore returns the number of elements assigned.

这里发生了很多事情。比较测试glob是否返回了恰好两个项目的列表(假设为。和..),但它如何做到这一点很棘手。内括号表示空列表。分配给此列表会将glob置于列表上下文中,以便返回目录中的所有文件。 (在标量上下文中,它的行为类似于迭代器,并且一次只返回一个。)赋值本身在标量上下文中进行评估(位于比较的右侧),因此返回分配的元素数。

The leading + is to prevent Perl from parsing the list as arguments to print. The trailing .empty concatenates the string "empty" to whatever came out of the list (i.e. either "not " or the empty string).

前导+是为了防止Perl将列表解析为打印参数。尾随.empty将字符串“empty”连接到列表中的任何内容(即“not”或空字符串)。

#2


<.* *>

is a glob consisting of two patterns: .* are all file names that start with . and * corresponds to all files (this is different than the usual DOS/Windows conventions).

是一个由两种模式组成的glob:。*是所有以。开头的文件名。和*对应所有文件(这与通常的DOS / Windows约定不同)。

(()=<.* *>)

evaluates the glob in list context, returning all the file names that match.

评估列表上下文中的glob,返回匹配的所有文件名。

Then, the comparison with 2 puts it into scalar context so 2 is compared to the number of files returned. If that number is 2, then the only directory entries are . and .., period. ;-)

然后,与2的比较将其置于标量上下文中,因此将2与返回的文件数进行比较。如果该数字是2,那么唯一的目录条目是。和...,期间。 ;-)

#3


<.* *> means (glob(".*"), glob("*")). glob expands file patterns the same way the shell does.

<。* *>表示(glob(“。*”),glob(“*”))。 glob以与shell相同的方式扩展文件模式。

#4


I find that the B::Deparse module helps quite a bit in deciphering some stuff that throws off most programmers' eyes, such as the q=...= construct:

我发现B :: Deparse模块可以解释一些抛出大多数程序员眼睛的东西,比如q = ... = construct:

$ perl -MO=Deparse,-p,-q,-sC 2>/dev/null << EOF
> print+(q=not =)[2==(()=<.* *>)].empty
> EOF
use File::Glob ();
print((('not ')[(2 == (() = glob('.* *')))] . 'empty'));

Of course, this doesn't instantly produce "readable" code, but it surely converts some of the stumbling blocks.

当然,这不会立即产生“可读”的代码,但肯定会转换一些绊脚石。

#5


The documentation for that feature is here. (Scroll near the end of the section)

该功能的文档在这里。 (在该部分末尾滚动)

#1


It's a golfed one-liner. The -e flag means to execute the rest of the command line as the program. The -l enables automatic line-end processing.

这是一个高尔夫单线。 -e标志表示执行命令行的其余部分作为程序。 -l启用自动行结束处理。

The <.* *> portion is a glob containing two patterns to expand: .* and *.

<。* *>部分是一个包含两个扩展模式的glob:。*和*。

This portion

(q=not =)

is a list containing a single value -- the string "not". The q=...= is an alternate string delimiter, apparently used because the single-quote is being used to quote the one-liner.

是包含单个值的列表 - 字符串“not”。 q = ... =是一个替代的字符串分隔符,显然是使用的,因为单引号用于引用单行。

The [...] portion is the subscript into that list. The value of the subscript will be either 0 (the value "not ") or 1 (nothing, which prints as the empty string) depending on the result of this comparison:

[...]部分是该列表的下标。下标的值将为0(值“not”)或1(nothing,打印为空字符串),具体取决于此比较的结果:

2 == (()=<.* *>)

There's a lot happening here. The comparison tests whether or not the glob returned a list of exactly two items (assumed to be . and ..) but how it does that is tricky. The inner parentheses denote an empty list. Assigning to this list puts the glob in list context so that it returns all the files in the directory. (In scalar context it would behave like an iterator and return only one at a time.) The assignment itself is evaluated in scalar context (being on the right hand side of the comparison) and therefore returns the number of elements assigned.

这里发生了很多事情。比较测试glob是否返回了恰好两个项目的列表(假设为。和..),但它如何做到这一点很棘手。内括号表示空列表。分配给此列表会将glob置于列表上下文中,以便返回目录中的所有文件。 (在标量上下文中,它的行为类似于迭代器,并且一次只返回一个。)赋值本身在标量上下文中进行评估(位于比较的右侧),因此返回分配的元素数。

The leading + is to prevent Perl from parsing the list as arguments to print. The trailing .empty concatenates the string "empty" to whatever came out of the list (i.e. either "not " or the empty string).

前导+是为了防止Perl将列表解析为打印参数。尾随.empty将字符串“empty”连接到列表中的任何内容(即“not”或空字符串)。

#2


<.* *>

is a glob consisting of two patterns: .* are all file names that start with . and * corresponds to all files (this is different than the usual DOS/Windows conventions).

是一个由两种模式组成的glob:。*是所有以。开头的文件名。和*对应所有文件(这与通常的DOS / Windows约定不同)。

(()=<.* *>)

evaluates the glob in list context, returning all the file names that match.

评估列表上下文中的glob,返回匹配的所有文件名。

Then, the comparison with 2 puts it into scalar context so 2 is compared to the number of files returned. If that number is 2, then the only directory entries are . and .., period. ;-)

然后,与2的比较将其置于标量上下文中,因此将2与返回的文件数进行比较。如果该数字是2,那么唯一的目录条目是。和...,期间。 ;-)

#3


<.* *> means (glob(".*"), glob("*")). glob expands file patterns the same way the shell does.

<。* *>表示(glob(“。*”),glob(“*”))。 glob以与shell相同的方式扩展文件模式。

#4


I find that the B::Deparse module helps quite a bit in deciphering some stuff that throws off most programmers' eyes, such as the q=...= construct:

我发现B :: Deparse模块可以解释一些抛出大多数程序员眼睛的东西,比如q = ... = construct:

$ perl -MO=Deparse,-p,-q,-sC 2>/dev/null << EOF
> print+(q=not =)[2==(()=<.* *>)].empty
> EOF
use File::Glob ();
print((('not ')[(2 == (() = glob('.* *')))] . 'empty'));

Of course, this doesn't instantly produce "readable" code, but it surely converts some of the stumbling blocks.

当然,这不会立即产生“可读”的代码,但肯定会转换一些绊脚石。

#5


The documentation for that feature is here. (Scroll near the end of the section)

该功能的文档在这里。 (在该部分末尾滚动)