Я конвертирую старую систему из пакетных файлов Windows в php для запуска на Debian Box. Я столкнулся с некоторыми вьющимися командами xcopy и удивляюсь, какой эквивалентный код для них будет в php.
xcopy src dest /Q /R /S /Y /exclude:c:\exclusions.txt
xcopy src dest /C /I /Q /R /S /U /Y /exclude:c:\exclusions.txt
http://ss64.com/nt/xcopy.html услужливо говорит мне, что переключатели:
/C = continue if error
/I = assume destination is a folder
/Q = quiet (no output)
/R = overwrite read only files
/S = copy folders and subfolders recursively
/U = copy only files that exist in the destination
/Y = supress prompt to overwrite destination file (and assume YES)
c:\exclusions.txt
просто есть имена файлов, чтобы пропустить
.ds_store
thumbs.db
.git
.ssh
.htaccess
README.MD
Переключатели, которые мне больше всего интересны, это /U
, /R
а также /S
— Как рекурсивно копировать структуру папок, только копируя соответствующие файлы, которые существуют в структуре назначения.
Я предполагаю, что мне придется использовать exec () из php, но не уверен, что я должен работать. Любые указатели оценили 🙂
Просто чтобы дать вам подсказку о правильном направлении, я бы начал с Компонент командной строки Symfony
Затем вы можете закодировать ключи в -q или —quiet вместо / Q и затем построить логику с помощью php файл функции.
Сказав все это, если вы действительно не хотите забавного упражнения по кодированию php, вероятно, было бы лучше использовать скрипт bash или аналогичный и использовать команду cp.
Хм, другой проект, та же проблема и снова нашел свой вопрос! Вот что я сделал на этот раз (где cp / rsync не всегда доступен):
// php xcopy, assumes /s /q /c /y /r switches
// /exclude switch via skipfiles and skipfolders (appended to in-built defaults)
// /u switch via $ifindest
public static function xcopy($source, $dest, $skipfiles = [], $skipfolders = [], $ifindest = false) {
// ensure source and destination end in one directory separator
$source = rtrim($source,DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;
$dest = rtrim($dest,DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;
// normalise skip arrays and apply defaults
$skipfolders = array_unique(array_merge(['.git','.ssh','editor'], array_map('rtrim', $skipfolders, array_fill(0, count($skipfolders), DIRECTORY_SEPARATOR))));
$skipfiles = array_unique(array_merge(['.ds_store','.htaccess','thumbs.db','about.txt','readme.md'], array_map('strtolower', $skipfiles)));
// examine folders and files using an iterator to avoid exposing functional recursion
foreach ($iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::SELF_FIRST) as $item) {
$name = strtolower($iterator->getFilename());
$path = $iterator->getSubPathName();
$folders = explode(DIRECTORY_SEPARATOR, empty($iterator->getSubPath()) ? $iterator->getSubPathName() : $iterator->getSubPath()); // subpath is empty at source root folder
$skip = count(array_intersect($folders,$skipfolders))>0;
// skip this iteration due to a folder match?
if ($skip) continue;
// skip this iteration due to a file match?
if ($item->isFile() && in_array($name, $skipfiles)) continue;
if ($item->isDir()) {
if (!file_exists("{$dest}{$path}")) {
// create destination folder structure
mkdir($dest.$path,0775,true);
}
} else {
if ($ifindest) {
if (!file_exists("{$dest}{$path}")) continue; // copy only if file exists in destination already
}
// finally we can copy the file
copy($path,$dest.$path);
}
}
}
Здесь есть несколько заметных пробелов, особенно в том, что здесь нет обработки исключений, но на этот раз это избавило меня от неприятностей.