I have 11 files with spaces in its name in a folder and I want to copy the newest 10. I used ls -t | head -n 10 to get only the newest 10 files. When I want to use the expression in a cp statement I get an error that the files could not be found because of the space in the name.E.g.: cp: cannot stat 10: No such file or directory for a file named 10 abc.pdfThe cp statement: cp $(ls -t | head -n 10) ~/...How do I get this working?
Use output from head to copy files with spaces
command line;pipe;cp;head
If you're using Bash and you want a 100% safe method (which, I guess, you want, now that you've learned the hard way that you must handle filenames seriously), here you go:shopt -s nullglobwhile IFS= read -r file; do    file=${file#* }    eval file=$file    cp $file Destinationdone < <(    for f in *; do        printf '%s %q\n' $(date -r $f +'%s') $f    done | sort -rn | head -n10)Let's have a look at its several parts:for f in *; do    printf '%s %q\n' $(date -r $f +'%s') $fdoneThis will print to stdout terms of the formTimestamp Filenamewhere timestamp is the modification date (obtained with -r's option to date) in seconds since Epoch and Filename is a quoted version of the filename that can be reused as shell input (see help printf and the %q format specifier). These lines are then sorted (numerically, in reverse order) with sort, and only the first 10 ones are kept.This is then fed to the while loop. The timestamps are removed with the file=${file# *} assignment (this gets rid of everything up to and including the first space), then the apparently dangerous line eval file=$file gets rid of the escape characters introduced by printf %q, and finally we can safely copy the file.Probably not the best approach or implementation, but 100% guaranteed safe regarding any possible filenames, and gets the job done. Though, this will treat regular files, directories, etc. all the same. If you want to restrict to regular files, add [[ -f $f ]] || continue just after the for f in *; do line. Also, it will not consider hidden files. If you want hidden files (but not . nor .., of course), add shopt -s dotglob.Another 100% Bash solution is to use Bash directly to sort the files. Here's an approach using a quicksort:quicksort() {    # quicksorts the filenames passed as positional parameters    # wrt modification time, newest first    # return array is quicksort_ret    if (($#==0)); then        quicksort_ret=()        return    fi    local pivot=$1 oldest=() newest=() f    shift    for f; do        if [[ $f -nt $pivot ]]; then            newest+=( $f )        else            oldest+=( $f )        fi    done    quicksort ${oldest[@]}    oldest=( ${quicksort_ret[@]} )    quicksort ${newest[@]}    quicksort_ret+=( $pivot ${oldest[@]} )}Then, sort them out, keep the first 10 ones, and copy them to your destination:$ shopt -s nullglob$ quicksort *$ cp -- ${quicksort_ret[@]:0:10} DestinationSame as the previous method, this will treat regular files, directories, etc. all the same and skip hidden files.For another approach: if your ls has the i and q arguments, you can use something along these lines:ls -tiq | head -n10 | cut -d ' ' -f1 | xargs -I X find -inum X -exec cp {} Destination \; -quitThis will show the file's inode, and find can perform commands on files refered to by their inode.Same thing, this will also treat directories, etc., not just regular files. I don't really like this one, as it relies too much on ls's output format