如何使用vala递归复制目录?

时间:2013-05-09 03:14:00

标签: file-io vala

我是Vala的新手,所以这可能是一个愚蠢的问题。

根据gimpnet上的#vala,无法使用 Glib.File.copy 递归复制目录。目前我正在使用:

Posix.system("cp -r absolutesource absolutedestination")

有更好的方法吗?

2 个答案:

答案 0 :(得分:3)

正如我在IRC中告诉你的那样,你可以通过为要复制的每个文件调用GLib.File.copy来自己编写一个函数。这是一个基本的例子:

public bool copy_recursive (GLib.File src, GLib.File dest, GLib.FileCopyFlags flags = GLib.FileCopyFlags.NONE, GLib.Cancellable? cancellable = null) throws GLib.Error {
  GLib.FileType src_type = src.query_file_type (GLib.FileQueryInfoFlags.NONE, cancellable);
  if ( src_type == GLib.FileType.DIRECTORY ) {
    dest.make_directory (cancellable);
    src.copy_attributes (dest, flags, cancellable);

    string src_path = src.get_path ();
    string dest_path = dest.get_path ();
    GLib.FileEnumerator enumerator = src.enumerate_children (GLib.FileAttribute.STANDARD_NAME, GLib.FileQueryInfoFlags.NONE, cancellable);
    for ( GLib.FileInfo? info = enumerator.next_file (cancellable) ; info != null ; info = enumerator.next_file (cancellable) ) {
      copy_recursive (
        GLib.File.new_for_path (GLib.Path.build_filename (src_path, info.get_name ())),
        GLib.File.new_for_path (GLib.Path.build_filename (dest_path, info.get_name ())),
        flags,
        cancellable);
    }
  } else if ( src_type == GLib.FileType.REGULAR ) {
    src.copy (dest, flags, cancellable);
  }

  return true;
}

另外,值得注意的是,您可能希望使用GLib.Process中的一个函数而不是Posix.system。

答案 1 :(得分:0)

我遇到了这个问题,在 C 中使用 GLib/GIO 寻找类似的东西。

这是我尝试将上面的 C++ 代码转换为 C

gboolean
copy_recursive(GFile *src, GFile *dest, GFileCopyFlags flags, GCancellable *cancellable, GError **error) {
    GFileType src_type = g_file_query_file_type(src, G_FILE_QUERY_INFO_NONE, cancellable);
    if (src_type == G_FILE_TYPE_DIRECTORY) {
        g_file_make_directory(dest, cancellable, error);
        g_file_copy_attributes(src, dest, flags, cancellable, error);

        GFileEnumerator *enumerator = g_file_enumerate_children(src, G_FILE_ATTRIBUTE_STANDARD_NAME, G_FILE_QUERY_INFO_NONE, cancellable, error);
        for (GFileInfo *info = g_file_enumerator_next_file(enumerator, cancellable, error); info != NULL; info = g_file_enumerator_next_file(enumerator, cancellable, error)) {
            const char *relative_path = g_file_info_get_name(info);
            copy_recursive(
                g_file_resolve_relative_path(src, relative_path),
                g_file_resolve_relative_path(dest, relative_path),
                flags, cancellable, error);
        }
    } else if (src_type == G_FILE_TYPE_REGULAR) {
        g_file_copy(src, dest, flags, cancellable, NULL, NULL, error);
    }

    return TRUE;
}

作为奖励,这里有一个递归删除目录的函数

gboolean
delete_recursive(GFile *file, GCancellable *cancellable, GError **error) {
    GFileType file_type = g_file_query_file_type(file, G_FILE_QUERY_INFO_NONE, cancellable);
    if (file_type == G_FILE_TYPE_DIRECTORY) {
        GFileEnumerator *enumerator = g_file_enumerate_children(file, G_FILE_ATTRIBUTE_STANDARD_NAME, G_FILE_QUERY_INFO_NONE, cancellable, error);
        for (GFileInfo *info = g_file_enumerator_next_file(enumerator, cancellable, error); info != NULL; info = g_file_enumerator_next_file(enumerator, cancellable, error)) {
            delete_recursive(
                g_file_resolve_relative_path(file, g_file_info_get_name(info)),
                cancellable, error);
        }
        g_file_delete(file, cancellable, error);
    } else if (file_type == G_FILE_TYPE_REGULAR) {
        g_file_delete(file, cancellable, error);
    }

    return TRUE;
}