shell

Why doesn't this xargs and mv command work?


I want to mv the latest file to the specified directory.

ls -1t ~/Downloads | head -1 | gsed 's|^|~/Downloads/|g' | xargs -I {} mv {} ~/test/

Output:

mv: rename ~/Downloads/latest.jpg to /Users/home/test: No such file or directory

But following command does work:

mv ~/Downloads/latest.jpg ~/test/

So I think the reason it doesn't work is the xargs command.

My environment is MacOS.


Solution

  • The immediate problem is that ~ isn't expanded by either xargs or mv, so your command is looking for a filename with a literal ~ character in it.

    The larger problem is that trying to parse output from ls is innately unreliable.

    Using BashFAQ #99 practices to find the latest file without resorting to ls -t:

    #!/usr/bin/env bash
    
    # Underscore prefixes avoid restricting destination variable names
    newest_file() {
      local _file
      local -n _dest_var=$1; shift
      _dest_var=$1; shift || return
      for _file; do
        [[ $_file -nt $_dest_var ]] && _dest_var=$_file
      done
    }
    
    newest_file newest ~/Downloads/*
    mv -- "$newest" ~/test
    

    This avoids the problem because the ~ characters -- used in an unquoted context in your source code -- are shell syntax rather than data; the shell replaces ~/test with /home/youruser/test before mv is started.