How can I use xargs to copy files that have spaces and quotes in their names?

后端 未结 22 1058
春和景丽
春和景丽 2020-12-02 03:49

I\'m trying to copy a bunch of files below a directory and a number of the files have spaces and single-quotes in their names. When I try to string together find

相关标签:
22条回答
  • 2020-12-02 04:26
    find | perl -lne 'print quotemeta' | xargs ls -d
    

    I believe that this will work reliably for any character except line-feed (and I suspect that if you've got line-feeds in your filenames, then you've got worse problems than this). It doesn't require GNU findutils, just Perl, so it should work pretty-much anywhere.

    0 讨论(0)
  • 2020-12-02 04:27

    I used Bill Star's answer slightly modified on Solaris:

    find . -mtime +2 | perl -pe 's{^}{\"};s{$}{\"}' > ~/output.file
    

    This will put quotes around each line. I didn't use the '-l' option although it probably would help.

    The file list I was going though might have '-', but not newlines. I haven't used the output file with any other commands as I want to review what was found before I just start massively deleting them via xargs.

    0 讨论(0)
  • 2020-12-02 04:28

    If you are using Bash, you can convert stdout to an array of lines by mapfile:

    find . | grep "FooBar" | (mapfile -t; cp "${MAPFILE[@]}" ~/foobar)
    

    The benefits are:

    • It's built-in, so it's faster.
    • Execute the command with all file names in one time, so it's faster.
    • You can append other arguments to the file names. For cp, you can also:

      find . -name '*FooBar*' -exec cp -t ~/foobar -- {} +
      

      however, some commands don't have such feature.

    The disadvantages:

    • Maybe not scale well if there are too many file names. (The limit? I don't know, but I had tested with 10 MB list file which includes 10000+ file names with no problem, under Debian)

    Well... who knows if Bash is available on OS X?

    0 讨论(0)
  • 2020-12-02 04:29

    For me, I was trying to do something a little different. I wanted to copy my .txt files into my tmp folder. The .txt filenames contain spaces and apostrophe characters. This worked on my Mac.

    $ find . -type f -name '*.txt' | sed 's/'"'"'/\'"'"'/g' | sed 's/.*/"&"/'  | xargs -I{} cp -v {} ./tmp/
    
    0 讨论(0)
  • 2020-12-02 04:31

    find . -print0 | grep --null 'FooBar' | xargs -0 ...

    I don't know about whether grep supports --null, nor whether xargs supports -0, on Leopard, but on GNU it's all good.

    0 讨论(0)
  • I created a small portable wrapper script called "xargsL" around "xargs" which addresses most of the problems.

    Contrary to xargs, xargsL accepts one pathname per line. The pathnames may contain any character except (obviously) newline or NUL bytes.

    No quoting is allowed or supported in the file list - your file names may contain all sorts of whitespace, backslashes, backticks, shell wildcard characters and the like - xargsL will process them as literal characters, no harm done.

    As an added bonus feature, xargsL will not run the command once if there is no input!

    Note the difference:

    $ true | xargs echo no data
    no data
    
    $ true | xargsL echo no data # No output
    

    Any arguments given to xargsL will be passed through to xargs.

    Here is the "xargsL" POSIX shell script:

    #! /bin/sh
    # Line-based version of "xargs" (one pathname per line which may contain any
    # amount of whitespace except for newlines) with the added bonus feature that
    # it will not execute the command if the input file is empty.
    #
    # Version 2018.76.3
    #
    # Copyright (c) 2018 Guenther Brunthaler. All rights reserved.
    #
    # This script is free software.
    # Distribution is permitted under the terms of the GPLv3.
    
    set -e
    trap 'test $? = 0 || echo "$0 failed!" >& 2' 0
    
    if IFS= read -r first
    then
            {
                    printf '%s\n' "$first"
                    cat
            } | sed 's/./\\&/g' | xargs ${1+"$@"}
    fi
    

    Put the script into some directory in your $PATH and don't forget to

    $ chmod +x xargsL

    the script there to make it executable.

    0 讨论(0)
提交回复
热议问题