From 24012743b8e2e77f5785cc7f17f0f0dd72d3aacd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Simon?= Date: Tue, 30 Oct 2012 20:49:01 +0100 Subject: [PATCH 1/2] [Finder] Added bsd adapter (need tests). --- .../Finder/Adapter/AbstractFindAdapter.php | 352 ++++++++++++++++++ .../Finder/Adapter/BsdFindAdapter.php | 51 +++ .../Finder/Adapter/GnuFindAdapter.php | 312 +--------------- src/Symfony/Component/Finder/Finder.php | 2 + 4 files changed, 411 insertions(+), 306 deletions(-) create mode 100644 src/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php create mode 100644 src/Symfony/Component/Finder/Adapter/BsdFindAdapter.php diff --git a/src/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php b/src/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php new file mode 100644 index 0000000000000..82ef7dbb9ad98 --- /dev/null +++ b/src/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php @@ -0,0 +1,352 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Adapter; + +use Symfony\Component\Finder\Iterator; +use Symfony\Component\Finder\Shell\Shell; +use Symfony\Component\Finder\Expression\Expression; +use Symfony\Component\Finder\Shell\Command; +use Symfony\Component\Finder\Iterator\SortableIterator; +use Symfony\Component\Finder\Comparator\NumberComparator; +use Symfony\Component\Finder\Comparator\DateComparator; + +/** + * Shell engine implementation using GNU find command. + * + * @author Jean-François Simon + */ +abstract class AbstractFindAdapter extends AbstractAdapter +{ + /** + * @var Shell + */ + protected $shell; + + /** + * Constructor. + */ + public function __construct() + { + $this->shell = new Shell(); + } + + /** + * {@inheritdoc} + */ + public function searchInDirectory($dir) + { + // having "/../" in path make find fail + $dir = realpath($dir); + + // searching directories containing or not containing strings leads to no result + if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode && ($this->contains || $this->notContains)) { + return new Iterator\FilePathsIterator(array(), $dir); + } + + $command = Command::create(); + + $find = $command + ->ins('find') + ->add('find ') + ->arg($dir) + ->add('-noleaf') // -noleaf option is required for filesystems who doesn't follow '.' and '..' convention + ->add('-regextype posix-extended'); + + if ($this->followLinks) { + $find->add('-follow'); + } + + $find->add('-mindepth')->add($this->minDepth+1); + // warning! INF < INF => true ; INF == INF => false ; INF === INF => true + // https://bugs.php.net/bug.php?id=9118 + if (INF !== $this->maxDepth) { + $find->add('-maxdepth')->add($this->maxDepth+1); + } + + if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode) { + $find->add('-type d'); + } elseif (Iterator\FileTypeFilterIterator::ONLY_FILES === $this->mode) { + $find->add('-type f'); + } + + $this->buildNamesFiltering($find, $this->names); + $this->buildNamesFiltering($find, $this->notNames, true); + $this->buildPathsFiltering($find, $dir, $this->paths); + $this->buildPathsFiltering($find, $dir, $this->notPaths, true); + $this->buildSizesFiltering($find, $this->sizes); + $this->buildDatesFiltering($find, $this->dates); + + $useGrep = $this->shell->testCommand('grep') && $this->shell->testCommand('xargs'); + $useSort = is_int($this->sort) && $this->shell->testCommand('sort') && $this->shell->testCommand('cut'); + + if ($useGrep && ($this->contains || $this->notContains)) { + $grep = $command->ins('grep'); + $this->buildContentFiltering($grep, $this->contains); + $this->buildContentFiltering($grep, $this->notContains, true); + } + + if ($useSort) { + $this->buildSorting($command, $this->sort); + } + + $paths = $this->shell->testCommand('uniq') ? $command->add('| uniq')->execute() : array_unique($command->execute()); + $iterator = new Iterator\FilePathsIterator($paths, $dir); + + if ($this->exclude) { + $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude); + } + + if (!$useGrep && ($this->contains || $this->notContains)) { + $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains); + } + + if ($this->filters) { + $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters); + } + + if (!$useSort && $this->sort) { + $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort); + $iterator = $iteratorAggregate->getIterator(); + } + + return $iterator; + } + + /** + * {@inheritdoc} + */ + public function isSupported() + { + return $this->shell->testCommand('find'); + } + + /** + * @param Command $command + * @param string[] $names + * @param bool $not + */ + private function buildNamesFiltering(Command $command, array $names, $not = false) + { + if (0 === count($names)) { + return; + } + + $command->add($not ? '-not' : null)->cmd('('); + + foreach ($names as $i => $name) { + $expr = Expression::create($name); + + // Fixes 'not search' and 'full path matching' regex problems. + // - Jokers '.' are replaced by [^/]. + // - We add '[^/]*' before and after regex (if no ^|$ flags are present). + if ($expr->isRegex()) { + $regex = $expr->getRegex(); + $regex->prepend($regex->hasStartFlag() ? '/' : '/[^/]*') + ->setStartFlag(false) + ->setStartJoker(true) + ->replaceJokers('[^/]'); + if (!$regex->hasEndFlag() || $regex->hasEndJoker()) { + $regex->setEndJoker(false)->append('[^/]*'); + } + } + + $command + ->add($i > 0 ? '-or' : null) + ->add($expr->isRegex() + ? ($expr->isCaseSensitive() ? '-regex' : '-iregex') + : ($expr->isCaseSensitive() ? '-name' : '-iname') + ) + ->arg($expr->renderPattern()); + } + + $command->cmd(')'); + } + + /** + * @param Command $command + * @param string $dir + * @param string[] $paths + * @param bool $not + * @return void + */ + private function buildPathsFiltering(Command $command, $dir, array $paths, $not = false) + { + if (0 === count($paths)) { + return; + } + + $command->add($not ? '-not' : null)->cmd('('); + + foreach ($paths as $i => $path) { + $expr = Expression::create($path); + + // Fixes 'not search' regex problems. + if ($expr->isRegex()) { + $regex = $expr->getRegex(); + $regex->prepend($regex->hasStartFlag() ? '' : '.*')->setEndJoker(!$regex->hasEndFlag()); + } else { + $expr->prepend('*')->append('*'); + } + + $command + ->add($i > 0 ? '-or' : null) + ->add($expr->isRegex() + ? ($expr->isCaseSensitive() ? '-regex' : '-iregex') + : ($expr->isCaseSensitive() ? '-path' : '-ipath') + ) + ->arg($expr->prepend($dir.DIRECTORY_SEPARATOR)->renderPattern()); + } + + $command->cmd(')'); + } + + /** + * @param Command $command + * @param NumberComparator[] $sizes + */ + private function buildSizesFiltering(Command $command, array $sizes) + { + foreach ($sizes as $i => $size) { + $command->add($i > 0 ? '-and' : null); + + if ('<=' === $size->getOperator()) { + $command->add('-size -'.($size->getTarget()+1).'c'); + continue; + } + + if ('<' === $size->getOperator()) { + $command->add('-size -'.$size->getTarget().'c'); + continue; + } + + if ('>=' === $size->getOperator()) { + $command->add('-size +'.($size->getTarget()-1).'c'); + continue; + } + + if ('>' === $size->getOperator()) { + $command->add('-size +'.$size->getTarget().'c'); + continue; + } + + if ('!=' === $size->getOperator()) { + $command->add('-size -'.$size->getTarget().'c'); + $command->add('-size +'.$size->getTarget().'c'); + continue; + } + + $command->add('-size '.$size->getTarget().'c'); + } + } + + /** + * @param Command $command + * @param DateComparator[] $dates + */ + private function buildDatesFiltering(Command $command, array $dates) + { + foreach ($dates as $i => $date) { + $command->add($i > 0 ? '-and' : null); + + $mins = (int) round((time()-$date->getTarget())/60); + + if (0 > $mins) { + // mtime is in the future + $command->add(' -mmin -0'); + // we will have no result so we don't need to continue + return; + } + + if ('<=' === $date->getOperator()) { + $command->add('-mmin +'.($mins-1)); + continue; + } + + if ('<' === $date->getOperator()) { + $command->add('-mmin +'.$mins); + continue; + } + + if ('>=' === $date->getOperator()) { + $command->add('-mmin -'.($mins+1)); + continue; + } + + if ('>' === $date->getOperator()) { + $command->add('-mmin -'.$mins); + continue; + } + + if ('!=' === $date->getOperator()) { + $command->add('-mmin +'.$mins.' -or -mmin -'.$mins); + continue; + } + + $command->add('-mmin '.$mins); + } + } + + /** + * @param Command $command + * @param array $contains + * @param bool $not + */ + private function buildContentFiltering(Command $command, array $contains, $not = false) + { + foreach ($contains as $contain) { + $expr = Expression::create($contain); + + // todo: avoid forking process for each $pattern by using multiple -e options + $command + ->add('| xargs -r grep -I') + ->add($expr->isCaseSensitive() ? null : '-i') + ->add($not ? '-L' : '-l') + ->add('-Ee')->arg($expr->renderPattern()); + } + } + + /** + * @param \Symfony\Component\Finder\Shell\Command $command + * @param string $sort + * @throws \InvalidArgumentException + */ + private function buildSorting(Command $command, $sort) + { + switch ($sort) { + case SortableIterator::SORT_BY_NAME: + $command->ins('sort')->add('| sort'); + return; + case SortableIterator::SORT_BY_TYPE: + $format = '%y'; + break; + case SortableIterator::SORT_BY_ACCESSED_TIME: + $format = '%A@'; + break; + case SortableIterator::SORT_BY_CHANGED_TIME: + $format = '%C@'; + break; + case SortableIterator::SORT_BY_MODIFIED_TIME: + $format = '%T@'; + break; + default: + throw new \InvalidArgumentException('Unknown sort options: '.$sort.'.'); + } + + $this->buildFormatSorting($command, $format); + } + + /** + * @param Command $command + * @param string $format + */ + abstract protected function buildFormatSorting(Command $command, $format); +} diff --git a/src/Symfony/Component/Finder/Adapter/BsdFindAdapter.php b/src/Symfony/Component/Finder/Adapter/BsdFindAdapter.php new file mode 100644 index 0000000000000..c70aaa5432407 --- /dev/null +++ b/src/Symfony/Component/Finder/Adapter/BsdFindAdapter.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Finder\Adapter; + +use Symfony\Component\Finder\Iterator; +use Symfony\Component\Finder\Shell\Shell; +use Symfony\Component\Finder\Expression\Expression; +use Symfony\Component\Finder\Shell\Command; +use Symfony\Component\Finder\Iterator\SortableIterator; + +/** + * Shell engine implementation using BSD find command. + * + * @author Jean-François Simon + */ +class BsdFindAdapter extends AbstractFindAdapter +{ + /** + * {@inheritdoc} + */ + public function isSupported() + { + return in_array($this->shell->getType(), array(Shell::TYPE_BSD, Shell::TYPE_DARWIN)) && parent::isSupported(); + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'bsd_find'; + } + + /** + * {@inheritdoc} + */ + protected function buildFormatSorting(Command $command, $format) + { + $command->get('find')->add('-print0 | xargs -0 stat -f')->arg($format.' %h/%f\\n') + ->add('| sort | cut')->arg('-d ')->arg('-f2-'); + } +} diff --git a/src/Symfony/Component/Finder/Adapter/GnuFindAdapter.php b/src/Symfony/Component/Finder/Adapter/GnuFindAdapter.php index 06d47cca840f5..aad78f920b6e8 100644 --- a/src/Symfony/Component/Finder/Adapter/GnuFindAdapter.php +++ b/src/Symfony/Component/Finder/Adapter/GnuFindAdapter.php @@ -16,117 +16,20 @@ use Symfony\Component\Finder\Expression\Expression; use Symfony\Component\Finder\Shell\Command; use Symfony\Component\Finder\Iterator\SortableIterator; -use Symfony\Component\Finder\Comparator\NumberComparator; -use Symfony\Component\Finder\Comparator\DateComparator; /** * Shell engine implementation using GNU find command. * * @author Jean-François Simon */ -class GnuFindAdapter extends AbstractAdapter +class GnuFindAdapter extends AbstractFindAdapter { - /** - * @var Shell - */ - private $shell; - - /** - * Constructor. - */ - public function __construct() - { - $this->shell = new Shell(); - } - - /** - * {@inheritdoc} - */ - public function searchInDirectory($dir) - { - // having "/../" in path make find fail - $dir = realpath($dir); - - // searching directories containing or not containing strings leads to no result - if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode && ($this->contains || $this->notContains)) { - return new Iterator\FilePathsIterator(array(), $dir); - } - - $command = Command::create(); - - $find = $command - ->ins('find') - ->add('find ') - ->arg($dir) - ->add('-noleaf') // -noleaf option is required for filesystems who doesn't follow '.' and '..' convention - ->add('-regextype posix-extended'); - - if ($this->followLinks) { - $find->add('-follow'); - } - - $find->add('-mindepth')->add($this->minDepth+1); - // warning! INF < INF => true ; INF == INF => false ; INF === INF => true - // https://bugs.php.net/bug.php?id=9118 - if (INF !== $this->maxDepth) { - $find->add('-maxdepth')->add($this->maxDepth+1); - } - - if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode) { - $find->add('-type d'); - } elseif (Iterator\FileTypeFilterIterator::ONLY_FILES === $this->mode) { - $find->add('-type f'); - } - - $this->buildNamesFiltering($find, $this->names); - $this->buildNamesFiltering($find, $this->notNames, true); - $this->buildPathsFiltering($find, $dir, $this->paths); - $this->buildPathsFiltering($find, $dir, $this->notPaths, true); - $this->buildSizesFiltering($find, $this->sizes); - $this->buildDatesFiltering($find, $this->dates); - - $useGrep = $this->shell->testCommand('grep') && $this->shell->testCommand('xargs'); - $useSort = is_int($this->sort) && $this->shell->testCommand('sort') && $this->shell->testCommand('cut'); - - if ($useGrep && ($this->contains || $this->notContains)) { - $grep = $command->ins('grep'); - $this->buildContentFiltering($grep, $this->contains); - $this->buildContentFiltering($grep, $this->notContains, true); - } - - if ($useSort) { - $this->buildSorting($command, $this->sort); - } - - $paths = $this->shell->testCommand('uniq') ? $command->add('| uniq')->execute() : array_unique($command->execute()); - $iterator = new Iterator\FilePathsIterator($paths, $dir); - - if ($this->exclude) { - $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude); - } - - if (!$useGrep && ($this->contains || $this->notContains)) { - $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains); - } - - if ($this->filters) { - $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters); - } - - if (!$useSort && $this->sort) { - $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort); - $iterator = $iteratorAggregate->getIterator(); - } - - return $iterator; - } - /** * {@inheritdoc} */ public function isSupported() { - return $this->shell->getType() === Shell::TYPE_UNIX && $this->shell->testCommand('find'); + return $this->shell->getType() === Shell::TYPE_UNIX && parent::isSupported(); } /** @@ -138,214 +41,11 @@ public function getName() } /** - * @param Command $command - * @param string[] $names - * @param bool $not - */ - private function buildNamesFiltering(Command $command, array $names, $not = false) - { - if (0 === count($names)) { - return; - } - - $command->add($not ? '-not' : null)->cmd('('); - - foreach ($names as $i => $name) { - $expr = Expression::create($name); - - // Fixes 'not search' and 'full path matching' regex problems. - // - Jokers '.' are replaced by [^/]. - // - We add '[^/]*' before and after regex (if no ^|$ flags are present). - if ($expr->isRegex()) { - $regex = $expr->getRegex(); - $regex->prepend($regex->hasStartFlag() ? '/' : '/[^/]*') - ->setStartFlag(false) - ->setStartJoker(true) - ->replaceJokers('[^/]'); - if (!$regex->hasEndFlag() || $regex->hasEndJoker()) { - $regex->setEndJoker(false)->append('[^/]*'); - } - } - - $command - ->add($i > 0 ? '-or' : null) - ->add($expr->isRegex() - ? ($expr->isCaseSensitive() ? '-regex' : '-iregex') - : ($expr->isCaseSensitive() ? '-name' : '-iname') - ) - ->arg($expr->renderPattern()); - } - - $command->cmd(')'); - } - - /** - * @param Command $command - * @param string $dir - * @param string[] $paths - * @param bool $not - * @return void - */ - private function buildPathsFiltering(Command $command, $dir, array $paths, $not = false) - { - if (0 === count($paths)) { - return; - } - - $command->add($not ? '-not' : null)->cmd('('); - - foreach ($paths as $i => $path) { - $expr = Expression::create($path); - - // Fixes 'not search' regex problems. - if ($expr->isRegex()) { - $regex = $expr->getRegex(); - $regex->prepend($regex->hasStartFlag() ? '' : '.*')->setEndJoker(!$regex->hasEndFlag()); - } else { - $expr->prepend('*')->append('*'); - } - - $command - ->add($i > 0 ? '-or' : null) - ->add($expr->isRegex() - ? ($expr->isCaseSensitive() ? '-regex' : '-iregex') - : ($expr->isCaseSensitive() ? '-path' : '-ipath') - ) - ->arg($expr->prepend($dir.DIRECTORY_SEPARATOR)->renderPattern()); - } - - $command->cmd(')'); - } - - /** - * @param Command $command - * @param NumberComparator[] $sizes - */ - private function buildSizesFiltering(Command $command, array $sizes) - { - foreach ($sizes as $i => $size) { - $command->add($i > 0 ? '-and' : null); - - if ('<=' === $size->getOperator()) { - $command->add('-size -'.($size->getTarget()+1).'c'); - continue; - } - - if ('<' === $size->getOperator()) { - $command->add('-size -'.$size->getTarget().'c'); - continue; - } - - if ('>=' === $size->getOperator()) { - $command->add('-size +'.($size->getTarget()-1).'c'); - continue; - } - - if ('>' === $size->getOperator()) { - $command->add('-size +'.$size->getTarget().'c'); - continue; - } - - if ('!=' === $size->getOperator()) { - $command->add('-size -'.$size->getTarget().'c'); - $command->add('-size +'.$size->getTarget().'c'); - continue; - } - - $command->add('-size '.$size->getTarget().'c'); - } - } - - /** - * @param Command $command - * @param DateComparator[] $dates - */ - private function buildDatesFiltering(Command $command, array $dates) - { - foreach ($dates as $i => $date) { - $command->add($i > 0 ? '-and' : null); - - $mins = (int) round((time()-$date->getTarget())/60); - - if (0 > $mins) { - // mtime is in the future - $command->add(' -mmin -0'); - // we will have no result so we don't need to continue - return; - } - - if ('<=' === $date->getOperator()) { - $command->add('-mmin +'.($mins-1)); - continue; - } - - if ('<' === $date->getOperator()) { - $command->add('-mmin +'.$mins); - continue; - } - - if ('>=' === $date->getOperator()) { - $command->add('-mmin -'.($mins+1)); - continue; - } - - if ('>' === $date->getOperator()) { - $command->add('-mmin -'.$mins); - continue; - } - - if ('!=' === $date->getOperator()) { - $command->add('-mmin +'.$mins.' -or -mmin -'.$mins); - continue; - } - - $command->add('-mmin '.$mins); - } - } - - /** - * @param Command $command - * @param array $contains - * @param bool $not + * {@inheritdoc} */ - private function buildContentFiltering(Command $command, array $contains, $not = false) + protected function buildFormatSorting(Command $command, $format) { - foreach ($contains as $contain) { - $expr = Expression::create($contain); - - // todo: avoid forking process for each $pattern by using multiple -e options - $command - ->add('| xargs -r grep -I') - ->add($expr->isCaseSensitive() ? null : '-i') - ->add($not ? '-L' : '-l') - ->add('-Ee')->arg($expr->renderPattern()); - } - } - - private function buildSorting(Command $command, $sort) - { - switch ($sort) { - case SortableIterator::SORT_BY_NAME: - $command->ins('sort')->add('| sort'); - return; - case SortableIterator::SORT_BY_TYPE: - $format = '%y'; - break; - case SortableIterator::SORT_BY_ACCESSED_TIME: - $format = '%A@'; - break; - case SortableIterator::SORT_BY_CHANGED_TIME: - $format = '%C@'; - break; - case SortableIterator::SORT_BY_MODIFIED_TIME: - $format = '%T@'; - break; - default: - throw new \InvalidArgumentException('Unknown sort options: '.$sort.'.'); - } - - $command->get('find')->add('-printf')->arg($format.' %h/%f\\n'); - $command->ins('sort')->add('| sort'); - $command->ins('awk')->add('| cut')->arg('-d ')->arg('-f2-'); + $command->get('find')->add('-printf')->arg($format.' %h/%f\\n') + ->add('| sort | cut')->arg('-d ')->arg('-f2-'); } } diff --git a/src/Symfony/Component/Finder/Finder.php b/src/Symfony/Component/Finder/Finder.php index b6b85d5239d99..cbaa9acaa336e 100644 --- a/src/Symfony/Component/Finder/Finder.php +++ b/src/Symfony/Component/Finder/Finder.php @@ -13,6 +13,7 @@ use Symfony\Component\Finder\Adapter\AdapterInterface; use Symfony\Component\Finder\Adapter\GnuFindAdapter; +use Symfony\Component\Finder\Adapter\BsdFindAdapter; use Symfony\Component\Finder\Adapter\PhpAdapter; use Symfony\Component\Finder\Exception\ExceptionInterface; @@ -65,6 +66,7 @@ public function __construct() $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES; $this->addAdapter(new GnuFindAdapter()); + $this->addAdapter(new BsdFindAdapter()); $this->addAdapter(new PhpAdapter(), -50); } From b5506777ea7c42894bbe2d0fcbc39cc62d97b91b Mon Sep 17 00:00:00 2001 From: Samy Dindane Date: Thu, 1 Nov 2012 15:28:05 +0100 Subject: [PATCH 2/2] [Finder] Fix the BSD adapter --- .../Finder/Adapter/AbstractFindAdapter.php | 22 +++++++++++++------ .../Finder/Adapter/GnuFindAdapter.php | 8 +++++++ .../Component/Finder/Tests/FinderTest.php | 2 +- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php b/src/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php index 82ef7dbb9ad98..9cde873a648f7 100644 --- a/src/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php +++ b/src/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php @@ -53,13 +53,7 @@ public function searchInDirectory($dir) } $command = Command::create(); - - $find = $command - ->ins('find') - ->add('find ') - ->arg($dir) - ->add('-noleaf') // -noleaf option is required for filesystems who doesn't follow '.' and '..' convention - ->add('-regextype posix-extended'); + $find = $this->buildFindCommand($command, $dir); if ($this->followLinks) { $find->add('-follow'); @@ -129,6 +123,20 @@ public function isSupported() return $this->shell->testCommand('find'); } + /** + * @param Command $command + * + * @return Command + */ + protected function buildFindCommand(Command $command, $dir) + { + return $command + ->ins('find') + ->add('find ') + ->arg($dir) + ->add('-noleaf'); // the -noleaf option is required for filesystems that don't follow the '.' and '..' conventions + } + /** * @param Command $command * @param string[] $names diff --git a/src/Symfony/Component/Finder/Adapter/GnuFindAdapter.php b/src/Symfony/Component/Finder/Adapter/GnuFindAdapter.php index aad78f920b6e8..b9e75e097b66d 100644 --- a/src/Symfony/Component/Finder/Adapter/GnuFindAdapter.php +++ b/src/Symfony/Component/Finder/Adapter/GnuFindAdapter.php @@ -48,4 +48,12 @@ protected function buildFormatSorting(Command $command, $format) $command->get('find')->add('-printf')->arg($format.' %h/%f\\n') ->add('| sort | cut')->arg('-d ')->arg('-f2-'); } + + /** + * {@inheritdoc} + */ + protected function buildFindCommand(Command $command, $dir) + { + return parent::buildFindCommand($command, $dir)->add('-regextype posix-extended'); + } } diff --git a/src/Symfony/Component/Finder/Tests/FinderTest.php b/src/Symfony/Component/Finder/Tests/FinderTest.php index aa17469a1a665..cf1109ebda2c2 100644 --- a/src/Symfony/Component/Finder/Tests/FinderTest.php +++ b/src/Symfony/Component/Finder/Tests/FinderTest.php @@ -202,7 +202,7 @@ public function testIgnoreDotFiles($adapter) $this->assertSame($finder, $finder->ignoreDotFiles(false)->ignoreVCS(false)); $this->assertIterator($this->toAbsolute(array('.git', '.bar', '.foo', '.foo/.bar', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator()); - $finder = new Finder(); + $finder = $this->buildFinder($adapter); $finder->ignoreDotFiles(false)->ignoreDotFiles(false)->ignoreVCS(false); $this->assertIterator($this->toAbsolute(array('.git', '.bar', '.foo', '.foo/.bar', 'foo', 'foo/bar.tmp', 'test.php', 'test.py', 'toto', 'foo bar')), $finder->in(self::$tmpDir)->getIterator());