Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用R';特定文件上的内部tar函数_R_Tar - Fatal编程技术网

使用R';特定文件上的内部tar函数

使用R';特定文件上的内部tar函数,r,tar,R,Tar,R有一个方便的跨平台tar()函数,可以对tar和gzip文件执行tar和gzip操作。这个函数似乎是为了给整个目录加焦油而设计的。我希望使用此函数对目录的子集或单个文件进行tar和压缩。然而,我似乎不能这样做。我希望以下内容能够在当前工作目录中为单个csv文件添加tar: tar( "tst.tgz", "myCsv.csv", compression="gzip" ) 那么,是否只能在目录上使用tar()函数 我通过创建一个临时目录,复制我的文件,然后给整个临时目录涂上焦油,暂时解决了这个

R有一个方便的跨平台tar()函数,可以对tar和gzip文件执行tar和gzip操作。这个函数似乎是为了给整个目录加焦油而设计的。我希望使用此函数对目录的子集或单个文件进行tar和压缩。然而,我似乎不能这样做。我希望以下内容能够在当前工作目录中为单个csv文件添加tar:

tar( "tst.tgz", "myCsv.csv", compression="gzip" )
那么,是否只能在目录上使用tar()函数


我通过创建一个临时目录,复制我的文件,然后给整个临时目录涂上焦油,暂时解决了这个问题。但我希望有一个更简单的解决方案。这将不需要复制文件,这对于大型文件来说有些费时

如果使用合适的模式运行
list.files()
(或其同义词
dir()
)为
files=
提供它要求的字符向量,会发生什么情况?我认为这里的帮助是明确的:

论据:

tarfile:tarfile:tilde扩展的路径名(请参见 将执行“path.expand”)。或者 可用于二进制写入的连接

文件:要存档的路径的字符向量:默认值 是归档当前目录下的所有文件


再次对其进行了修订,进一步简化了
tar1
代码。另外,
tar1
现在可以输出一个没有目录的文件或多个没有目录的文件。本质上,我们需要解决tar中R使用
list.files
的一个bug,我们通过重新定义
tar1
使用的
list.files
来实现这一点

操作
tar
环境的行实际上创建了
tar
的一个副本,其环境是
tar1
中的环境,因此当运行复制的
tar
时,它首先在那里查找
list.files
。如果我们没有在新环境中复制
tar
,那么它会使用R底部的
list.files
,忽略我们的重新定义

下面的
tar1
tar
命令的变体,该命令生成一个tar文件,其组件具有一个级别(即单个文件或一组没有目录的文件)。假定所有文件都在当前目录中

按照
tar1
的定义,我们通过创建两个文件并使用其中的第一个文件创建一个存档,然后使用这两个文件来测试它

# tar a single file
tar1 <- function(...) {
    list.files <- function(...) ..1
    environment(tar) <- environment()
    tar(...)
}

# test - first create test files, then some test runs of tar1
cat("a", file = "a.csv")
cat("b", file = "a.csv")

tar1("tst.tgz", "a.csv", "gzip")
tar1("tst2.tgz", Sys.glob("*.csv"), "gzip")
#对单个文件进行tar

tar1我认为这不可能像你描述的那样。
files
参数被传递到
list.files
path
参数,因此它通过对目录中的文件(而不是单个文件)加上焦油来工作

如果您准备编辑内部函数,
tar()
可以通过在
tar()
内部调用
list.files()
来完成您想要的操作。稍微修改一下就产生了下面的
tar2()
函数,它有额外的参数来控制
list.files()
返回的内容。使用此功能,我们可以通过如下调用实现您想要的:

tar2("foo.tar", path = ".", pattern = "bar.csv", recursive = FALSE, 
     full.names = FALSE, all.files = FALSE)
all.files=FALSE
可能是多余的,除非您的隐藏文件的名称包含
“bar.csv”

recursive=FALSE
位只会停止函数搜索除当前目录之外的任何位置,这似乎是您想要的,如果工作目录有很多文件和子文件夹,则会加快搜索速度

full.names=FALSE
位是键。如果此If
TRUE
list.files()
将匹配的文件名返回为
“/bar.csv”
,而
tar()
将粘贴在tarball内的文件夹中。如果我们将其设置为
FALSE
list.files()
返回
“bar.csv”
,那么我们将根据请求获得一个带有单个csv文件的tarball

如果您有名称相似的文件,并且只希望找到指定的文件名,请在模式中用
^
$
将其固定,例如:

tar2("foo.tar", path = ".", pattern = "^bar.csv$", recursive = FALSE, 
     full.names = FALSE, all.files = FALSE)
下面是修改后的
tar()
函数作为
tar2()


tar2是的,我的问题应该更详细一些。我从那开始…让我把问题改成一个文件的简单情况,这是我开始问的,但后来转到了通配符情况中间的问题。我感觉我试图让tar()做一些它不打算做的事情。感谢您的确认;)@JD Long如果您编辑
tar()
函数以接受不同的参数,则可以执行此操作。请看我更新的答案中的一个解决方案。在看了这个之后,我一直在考虑是否使用补丁来接近R-devel。这将使
tar()
更加有用。不过,在提出之前,我需要先做一点检查。@Gavin Simpson,我认为提交它是值得的,但我认为应该简化接口,只是为了有一个files参数,而不是
tar
当前没有的额外参数。这些额外的参数使其更易于实现,但对用户来说并不方便。“无论如何,我已经给你的职位投了一票,”格洛森迪耶克同意。我发布的
tar2()
只是@JD可以利用的东西。我需要按照你提到的思路考虑一个提议的改变
list.files()
无法使用我们可能希望使用的tar,因此它可能需要一些修改以避免额外的参数。它在我的系统上工作。我已将输出添加到帖子中以显示。@JD Long将他的Q简化为试图对单个声明的csv文件进行tar。我已按照答案第一句中的讨论修改了答案。感谢您的回答。我需要研究tar()函数,然后研究你的答案,以便完全理解这里发生的事情
tar2 <- function (tarfile, files = NULL, compression = c("none", "gzip", 
    "bzip2", "xz"), compression_level = 6, tar = Sys.getenv("tar"),
    pattern = NULL, all.files = TRUE, recursive = TRUE, full.names = TRUE) 
{
    if (is.character(tarfile)) {
        TAR <- tar
        if (nzchar(TAR) && TAR != "internal") {
            flags <- switch(match.arg(compression), none = "cf", 
                gzip = "zcf", bzip2 = "jcf", xz = "Jcf")
            cmd <- paste(TAR, flags, shQuote(tarfile), paste(shQuote(files), 
                collapse = " "))
            return(invisible(system(cmd)))
        }
        con <- switch(match.arg(compression), none = file(tarfile, 
            "wb"), gzip = gzfile(tarfile, "wb", compress = compression_level), 
            bzip2 = bzfile(tarfile, "wb", compress = compression_level), 
            xz = xzfile(tarfile, "wb", compress = compression_level))
        on.exit(close(con))
    }
    else if (inherits(tarfile, "connection")) 
        con <- tarfile
    else stop("'tarfile' must be a character string or a connection")
    files <- list.files(files, recursive = recursive, all.files = all.files, 
        full.names = full.names, pattern = pattern)
    bf <- unique(dirname(files))
    files <- c(bf[!bf %in% c(".", files)], files)
    for (f in unique(files)) {
        info <- file.info(f)
        if (is.na(info$size)) {
            warning(gettextf("file '%s' not found", f), domain = NA)
            next
        }
        header <- raw(512L)
        if (info$isdir && !grepl("/$", f)) 
            f <- paste(f, "/", sep = "")
        name <- charToRaw(f)
        if (length(name) > 100L) {
            if (length(name) > 255L) 
                stop("file path is too long")
            s <- max(which(name[1:155] == charToRaw("/")))
            if (is.infinite(s) || s + 100 < length(name)) 
                stop("file path is too long")
            warning("storing paths of more than 100 bytes is not portable:\n  ", 
                sQuote(f), domain = NA)
            prefix <- name[1:(s - 1)]
            name <- name[-(1:s)]
            header[345 + seq_along(prefix)] <- prefix
        }
        header[seq_along(name)] <- name
        header[101:107] <- charToRaw(sprintf("%07o", info$mode))
        uid <- info$uid
        if (!is.null(uid) && !is.na(uid)) 
            header[109:115] <- charToRaw(sprintf("%07o", uid))
        gid <- info$gid
        if (!is.null(gid) && !is.na(gid)) 
            header[117:123] <- charToRaw(sprintf("%07o", gid))
        size <- ifelse(info$isdir, 0, info$size)
        header[137:147] <- charToRaw(sprintf("%011o", as.integer(info$mtime)))
        if (info$isdir) 
            header[157L] <- charToRaw("5")
        else {
            lnk <- Sys.readlink(f)
            if (is.na(lnk)) 
                lnk <- ""
            header[157L] <- charToRaw(ifelse(nzchar(lnk), "2", 
                "0"))
            if (nzchar(lnk)) {
                if (length(lnk) > 100L) 
                  stop("linked path is too long")
                header[157L + seq_len(nchar(lnk))] <- charToRaw(lnk)
                size <- 0
            }
        }
        header[125:135] <- charToRaw(sprintf("%011o", as.integer(size)))
        header[258:262] <- charToRaw("ustar")
        header[264:265] <- charToRaw("0")
        s <- info$uname
        if (!is.null(s) && !is.na(s)) {
            ns <- nchar(s, "b")
            header[265L + (1:ns)] <- charToRaw(s)
        }
        s <- info$grname
        if (!is.null(s) && !is.na(s)) {
            ns <- nchar(s, "b")
            header[297L + (1:ns)] <- charToRaw(s)
        }
        header[149:156] <- charToRaw(" ")
        checksum <- sum(as.integer(header))%%2^24
        header[149:154] <- charToRaw(sprintf("%06o", as.integer(checksum)))
        header[155L] <- as.raw(0L)
        writeBin(header, con)
        if (info$isdir || nzchar(lnk)) 
            next
        inf <- file(f, "rb")
        for (i in seq_len(ceiling(info$size/512L))) {
            block <- readBin(inf, "raw", 512L)
            writeBin(block, con)
            if ((n <- length(block)) < 512L) 
                writeBin(raw(512L - n), con)
        }
        close(inf)
    }
    block <- raw(512L)
    writeBin(block, con)
    writeBin(block, con)
    invisible(0L)
}