如何将具有属性/权限的目录从一个位置复制到另一个位置?

Posted

技术标签:

【中文标题】如何将具有属性/权限的目录从一个位置复制到另一个位置?【英文标题】:How to copy a directory with its attributes/permissions from one location to another? 【发布时间】:2013-07-12 13:51:48 【问题描述】:

我看到很多examples 使用Files.walkFileTree() 将目录及其内容从一个位置复制到另一个位置,但他们没有考虑到目录的文件属性和权限。意思是,他们只是调用Files.createDirectories(),没有任何属性或权限。

如何使用 Java7 核心类将目录(及其内容)从一个位置复制到另一个位置而不丢失文件属性或权限?

【问题讨论】:

另一个:***.com/a/20085222/281545 和香草一个:docs.oracle.com/javase/tutorial/essential/io/examples/Copy.java @Mr_and_Mrs_D,您引用的示例不复制文件权限(仅属性)。它们也不复制目录权限和属性。 【参考方案1】:

回答我自己的问题:

/**
 * Copies a directory.
 * <p>
 * NOTE: This method is not thread-safe.
 * <p>
 * 
 * @param source
 *            the directory to copy from
 * @param target
 *            the directory to copy into
 * @throws IOException
 *             if an I/O error occurs
 */
private static void copyDirectory(final Path source, final Path target)
        throws IOException 
    Files.walkFileTree(source, EnumSet.of(FileVisitOption.FOLLOW_LINKS),
        Integer.MAX_VALUE, new FileVisitor<Path>() 

            @Override
            public FileVisitResult preVisitDirectory(Path dir,
                    BasicFileAttributes sourceBasic) throws IOException 
                Path targetDir = Files.createDirectories(target
                    .resolve(source.relativize(dir)));
                AclFileAttributeView acl = Files.getFileAttributeView(dir,
                    AclFileAttributeView.class);
                if (acl != null)
                    Files.getFileAttributeView(targetDir,
                        AclFileAttributeView.class).setAcl(acl.getAcl());
                DosFileAttributeView dosAttrs = Files.getFileAttributeView(
                    dir, DosFileAttributeView.class);
                if (dosAttrs != null) 
                    DosFileAttributes sourceDosAttrs = dosAttrs
                        .readAttributes();
                    DosFileAttributeView targetDosAttrs = Files
                        .getFileAttributeView(targetDir,
                            DosFileAttributeView.class);
                    targetDosAttrs.setArchive(sourceDosAttrs.isArchive());
                    targetDosAttrs.setHidden(sourceDosAttrs.isHidden());
                    targetDosAttrs.setReadOnly(sourceDosAttrs.isReadOnly());
                    targetDosAttrs.setSystem(sourceDosAttrs.isSystem());
                
                FileOwnerAttributeView ownerAttrs = Files
                    .getFileAttributeView(dir, FileOwnerAttributeView.class);
                if (ownerAttrs != null) 
                    FileOwnerAttributeView targetOwner = Files
                        .getFileAttributeView(targetDir,
                            FileOwnerAttributeView.class);
                    targetOwner.setOwner(ownerAttrs.getOwner());
                
                PosixFileAttributeView posixAttrs = Files
                    .getFileAttributeView(dir, PosixFileAttributeView.class);
                if (posixAttrs != null) 
                    PosixFileAttributes sourcePosix = posixAttrs
                        .readAttributes();
                    PosixFileAttributeView targetPosix = Files
                        .getFileAttributeView(targetDir,
                            PosixFileAttributeView.class);
                    targetPosix.setPermissions(sourcePosix.permissions());
                    targetPosix.setGroup(sourcePosix.group());
                
                UserDefinedFileAttributeView userAttrs = Files
                    .getFileAttributeView(dir,
                        UserDefinedFileAttributeView.class);
                if (userAttrs != null) 
                    UserDefinedFileAttributeView targetUser = Files
                        .getFileAttributeView(targetDir,
                            UserDefinedFileAttributeView.class);
                    for (String key : userAttrs.list()) 
                        ByteBuffer buffer = ByteBuffer.allocate(userAttrs
                            .size(key));
                        userAttrs.read(key, buffer);
                        buffer.flip();
                        targetUser.write(key, buffer);
                    
                
                // Must be done last, otherwise last-modified time may be
                // wrong
                BasicFileAttributeView targetBasic = Files
                    .getFileAttributeView(targetDir,
                        BasicFileAttributeView.class);
                targetBasic.setTimes(sourceBasic.lastModifiedTime(),
                    sourceBasic.lastAccessTime(),
                    sourceBasic.creationTime());
                return FileVisitResult.CONTINUE;
            

            @Override
            public FileVisitResult visitFile(Path file,
                    BasicFileAttributes attrs) throws IOException 
                Files.copy(file, target.resolve(source.relativize(file)),
                    StandardCopyOption.COPY_ATTRIBUTES);
                return FileVisitResult.CONTINUE;
            

            @Override
            public FileVisitResult
                    visitFileFailed(Path file, IOException e)
                            throws IOException 
                throw e;
            

            @Override
            public FileVisitResult postVisitDirectory(Path dir,
                    IOException e) throws IOException 
                if (e != null) throw e;
                return FileVisitResult.CONTINUE;
            
        );

此代码尚未经过广泛测试,但对我有用。

【讨论】:

两个问题:1. 为什么不是原版的:docs.oracle.com/javase/tutorial/essential/io/examples/Copy.java 2. 为什么不是 SimpleFileVisitor 的实现 该设计还可以从一个枚举中受益,该枚举将在其构造函数中接受 Class @Mr_and_Mrs_D,“普通版”复制属性但不复制权限。您认为哪条线路会这样做? @Mr_and_Mrs_D,我不明白你对枚举和构造函数的意思。 Class&lt;T extends FileAttributeView&gt; 不是enum,也不清楚你指的是什么构造函数。 回复:枚举:dropbox.com/s/ngrwqnhzx7o7iqu/CopyDirectory.java。回复:香草一号 - 只是在问,我现在明白了。请注意,我将匿名类更改为嵌套并使其实现 SimpleFileVisitor(如 visitFileFailed 和 postVisitDirectory)在您的匿名实现中具有默认行为

以上是关于如何将具有属性/权限的目录从一个位置复制到另一个位置?的主要内容,如果未能解决你的问题,请参考以下文章

linux如何将一个目录下所有的文件都改成775的权限

如何将具有特定大小的字符复制到另一个图像中与原始图像相同的位置?

如何将文件从一个位置复制到另一个位置?

如何将文件从一个位置复制到另一个位置?

C# 使用安全/权限设置将文件夹复制到另一个目的地

如何使用 phonegap 将文件从一个位置移动/复制到另一个位置