使用regexp从Unix“ls -la”命令获取文件名?

时间:2009-10-17 10:42:50

标签: php regex unix

如何生成一个正则表达式模式,从其中任何一行返回文件名? (我将一次搜索一行)。

drwxrwxrwx  4 apache      apache       4096 Oct 14 09:40 .
drwxrwxrwx 11 apache      apache       4096 Oct 13 11:33 ..
-rwxrwxrwx  1 apache      apache      16507 Oct 17 10:16 .bash_history
-rwxrwxrwx  1 apache      apache         33 Sep  1 09:36 .bash_logout
-rwxrwxrwx  1 apache      apache        176 Sep  1 09:36 .bash_profile
-rwxrwxrwx  1 apache      apache        124 Sep  1 09:36 .bashrc
-rwxrwxrwx  1 apache      apache        515 Sep  1 09:36 .emacs
-rw-------  1 christoffer christoffer 11993 Sep 18 10:00 .mysql_history
drwxrwxrwx  3 apache      apache       4096 Sep  1 09:48 .subversion
-rwxrwxrwx  1 christoffer christoffer  9204 Oct 14 09:40 .viminfo
drwxrwxrwx 14 apache      apache       4096 Oct 12 07:39 www

使用PHP完成搜索,但我想这并没有真正有所作为。 :)

编辑:通过SSH连接检索文件列表,这就是我不使用内置PHP函数的原因。我需要这个完整的列表来查看文件是否实际上是一个目录。

11 个答案:

答案 0 :(得分:6)

请尝试使用ls -a1F。这将列出所有条目(-a),每行一个(-1),以及有关名称(-F)附加的文件类型的其他信息。

您可能会为您的目录获得类似的内容:

./
../
.bash_history
.bash_logout
.bash_profile
.bashrc
.emacs
.mysql_history
.subversion/
.viminfo
www/

目录末尾有一个斜杠/

答案 1 :(得分:5)

主要问题是......为什么?请改用readdirstat

<?php

$directory = './';
$dh = opendir($directory);

while (($file = readdir($dh)) !== false)
{
    $stat = stat($directory.$file);
    echo '<b>'.$directory.$file.':</b><br/>';
    var_dump($stat);
}

答案 2 :(得分:4)

如果您正在寻找目录,而不是解析ls输出,请使用find

find -maxdepth 1 -mindepth 1 -type d

这将列出如下目录:

./Documents
./.gnupg
./Download

您不再需要解析数据以确定什么是目录,什么不是。

如果你真的想要文件而不是目录,那么你可以使用-type f

您对ls输出的解析可能会在符号链接上中断...

答案 3 :(得分:2)

我不会使用正则表达式

给定一条线,你可以爆炸并弹出数组中的最后一个元素

if (preg_match('/^d/', $line)) {
    $name = array_pop(explode(' ', $line));
}

编辑:您的示例都没有嵌入空格,但后来的评论表明找到文件名

很重要

答案 4 :(得分:1)

使用spl和DirectoryIterator

在php5中有一个更好的方法
$dir = '.';
foreach (new DirectoryIterator($dir) as $fileInfo) {
    echo $fileInfo->getFilename() . "<br>\n";
}

答案 5 :(得分:1)

除了Matthew所说的,解析ls输出有很多理由。您可能在文件名中包含空格 - 甚至删除字符。列表的日期部分的格式,特别是对于旧文件的格式不同,大文件的大小可能会破坏列表。

如果你必须使用正则表达式,并且文件名中确实没有空格,那么只需绑定到行的末尾并获得你在那里找到的非空格

(\S+)$

答案 6 :(得分:1)

鉴于您使用完整目录列表的限制,我会这样做:

ls -l | egrep '^d' | awk '{print $NF}'

Egrep命令会在行的开头搜索字母“d”。默认情况下,awk使用空格作为分隔符,$ NF将为您提供最后一个元素。我能想到的唯一一个边缘情况是,在文件名中有空格的情况下,这种情况并不总是在100%的情况下工作。

我建议使用find命令:

find . -maxdepth 1 -type d | awk -F '/' '{print $NF}'

上面的find命令只会获取当前目录中的文件/目录(b / c为-maxdepth 1 arg)。 awk命令将使用'/'拆分行,并仅检索最后一个令牌($ NF)。

因为,awk命令

awk -F '/' '{print $NF}'

将为您提供最基本的元素:

find . -maxdepth x -type d

其中x是您选择的数字&gt; = 1,您仍然可以得到您想要的,文件名和/或目录名。

答案 7 :(得分:0)

\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+(\S+)

每个字符串由9个由空格分隔的部分构成。你正在寻找第9部分。

答案 8 :(得分:0)

改为使用glob('*')

答案 9 :(得分:0)

不是尝试解析困难的输出,而是首先生成一些更有用的输出。例如:

ssh user@machine 'cd /etc; for a in *; do [ -f "$a" ] && echo "$a"; done'

将在远程计算机上的/ etc中生成非目录文件列表。这应该更容易解析。

答案 10 :(得分:0)

也显示隐藏文件,如果您不相信我,请尝试使用。

 glob('{,.}*', GLOB_BRACE);