如果对服务器的唯一访问是通过 FTP,那么如何删除目录树中具有特定名称的所有目录?
为了澄清,我想遍历目录树并通过 FTP 删除名称与某个字符串匹配的每个目录。一种在 PHP 中实现这一点的方法会很好——我应该从哪里开始?此外,如果有人知道任何已经这样做的实用程序,那也很好。
这是一个起点 - 一个函数,它将扫描 FTP 目录并打印树中与模式匹配的任何目录的名称。我已经对其进行了简要测试。
function scan_ftp_dir($conn, $dir, $pattern) {
$files = ftp_nlist($conn, $dir);
if (!$files) {
return;
}
foreach ($files as $file) {
//the quickest way i can think of to check if is a directory
if (ftp_size($conn, $file) == -1) {
//get just the directory name
$dirName = substr($file, strrpos($file, '/') + 1);
if (preg_match($pattern, $dirName)) {
echo $file . ' matched pattern';
} else {
//directory didn't match pattern, recurse
scan_ftp_dir($conn, $file, $pattern);
}
}
}
}
然后做这样的事情
$host = 'localhost';
$user = 'user';
$pass = 'pass';
if (false === ($conn = ftp_connect($host))) {
die ('cannot connect');
}
if (!ftp_login($conn, $user, $pass)) die ('cannot authenticate');
scan_ftp_dir($conn, '.', '/^beginswith/');
不幸的是,您只能使用 删除一个空目录ftp_rmdir()
,但如果您查看此处,则有一个名为的函数ftp_rmAll()
,您可以使用它来删除您找到的整个目录结构。
此外,我只在 Unix 上测试了使用从返回的失败状态ftp_size()
作为检查返回的项目ftp_nlist()
是否是目录的方法的技巧。
大概这个问题比它最初出现的要多。
FTP支持DIR列出目录内容,RMDIR删除目录,DEL删除文件,所以它支持你需要的操作。
或者您在问如何遍历 FTP 目录树?
您对此有首选/必需的实现语言吗?
好吧,这是我最终使用的脚本。这是一个相当具体的实例,必须使用它,但如果您处于与我相同的困境中,只需输入您的 ftp 服务器地址、用户名、密码、您要删除的文件夹的名称以及路径要开始的文件夹,这将遍历目录,删除与名称匹配的所有文件夹。如果与服务器的连接断开,则重新连接会出现错误,因此如果它断开连接,您可能需要再次运行脚本。
if( $argc == 2 ) {
$directoryToSearch = $argv[1];
$host = '';
$username = '';
$password = '';
$connection = connect( $host, $username, $password );
deleteDirectoriesWithName( $connection, 'directoryToDelete', $directoryToSearch );
ftp_close( $connection );
exit( 0 );
}
else {
cliPrint( "This script currently only supports 1 argument.\n");
cliPrint( "Usage: php deleteDirectories.php directoryNameToSearch\n");
exit( 1 );
}
/**
* Recursively traverse directories and files starting with the path
* passed in and then delete all directories that match the name
* passed in
* @param $connection the connection resource to the database.
* @param $name the name of the directories that should be * deleted.
* @param $path the path to start searching from
*/
function deleteDirectoriesWithName( &$connection, $name, $path ) {
global $host, $username, $password;
cliPrint( "At path: $path\n" );
//Get a list of files in the directory
$list = ftp_nlist( $connection, $path );
if ( empty( $list ) ) {
$rawList = ftp_rawlist( $connection, $path );
if( empty( $rawList ) ) {
cliPrint( "Reconnecting\n");
ftp_close( $connection );
$connection = connect( $host, $username, $password );
cliPrint( "Reconnected\n" );
deleteDirectoriesWithName( $connection, $name, $path );
return true;
}
$pathToPass = addSlashToEnd( $path );
$list = RawlistToNlist( $rawList, $pathToPass );
}
//If we have selected a directory, then 'visit' the files (or directories) in the dir
if ( $list[0] != $path ) {
$path = addSlashToEnd( $path );
//iterate through all of the items listed in the directory
foreach ( $list as $item ) {
//if the directory matches the name to be deleted, delete it recursively
if ( $item == $name ) {
DeleteDirRecursive( $connection, $path . $item );
}
//otherwise continue traversing
else if ( $item != '..' && $item != '.' ) {
deleteDirectoriesWithName( $connection, $name, $path . $item );
}
}
}
return true;
}
/**
*Put output to STDOUT
*/
function cliPrint( $string ) {
fwrite( STDOUT, $string );
}
/**
*Connect to the ftp server
*/
function connect( $host, $username, $password ) {
$connection = ftp_connect( $host );
if ( !$connection ) {
die('Could not connect to server: ' . $host );
}
$loginSuccessful = ftp_login( $connection, $username, $password );
if ( !$loginSuccessful ) {
die( 'Could not login as: ' . $username . '@' . $host );
}
cliPrint( "Connection successful\n" );
return $connection;
}
/**
* Delete the provided directory and all its contents from the FTP-server.
*
* @param string $path Path to the directory on the FTP-server relative to
* the current working directory
*/
function DeleteDirRecursive(&$resource, $path) {
global $host, $username, $password;
cliPrint( $path . "\n" );
$result_message = "";
//Get a list of files and directories in the current directory
$list = ftp_nlist($resource, $path);
if ( empty($list) ) {
$listToPass = ftp_rawlist( $resource, $path );
if ( empty( $listToPass ) ) {
cliPrint( "Reconnecting\n" );
ftp_close( $resource );
$resource = connect( $host, $username, $password );
$result_message = "Reconnected\n";
cliPrint( "Reconnected\n" );
$result_message .= DeleteDirRecursive( $resource, $path );
return $result_message;
}
$list = RawlistToNlist( $listToPass, addSlashToEnd( $path ) );
}
//if the current path is a directory, recursively delete the file within and then
//delete the empty directory
if ($list[0] != $path) {
$path = addSlashToEnd( $path );
foreach ($list as $item) {
if ($item != ".." && $item != ".") {
$result_message .= DeleteDirRecursive($resource, $path . $item);
}
}
cliPrint( 'Delete: ' . $path . "\n" );
if (ftp_rmdir ($resource, $path)) {
cliPrint( "Successfully deleted $path\n" );
} else {
cliPrint( "There was a problem deleting $path\n" );
}
}
//otherwise delete the file
else {
cliPrint( 'Delete file: ' . $path . "\n" );
if (ftp_delete ($resource, $path)) {
cliPrint( "Successfully deleted $path\n" );
} else {
cliPrint( "There was a problem deleting $path\n" );
}
}
return $result_message;
}
/**
* Convert a result from ftp_rawlist() to a result of ftp_nlist()
*
* @param array $rawlist Result from ftp_rawlist();
* @param string $path Path to the directory on the FTP-server relative
* to the current working directory
* @return array An array with the paths of the files in the directory
*/
function RawlistToNlist($rawlist, $path) {
$array = array();
foreach ($rawlist as $item) {
$filename = trim(substr($item, 55, strlen($item) - 55));
if ($filename != "." || $filename != "..") {
$array[] = $filename;
}
}
return $array;
}
/**
*Adds a '/' to the end of the path if it is not already present.
*/
function addSlashToEnd( $path ) {
$endOfPath = substr( $path, strlen( $path ) - 1, 1 );
if( $endOfPath == '/' ) {
$pathEnding = '';
}
else {
$pathEnding = '/';
}
return $path . $pathEnding;
}