26

In Bash, suppose I visit a directory, and then another directory. I would like to copy a file from the first directory to the second directory, but without specifying the long pathnames of them. Is it possible?

My temporary solution is to use /tmp as a temporary place to store a copy of the file. cp myfile /tmp when I am in the first directory, and then cp /tmp/myfile . when I am in the second directory. But I may check if the file will overwrite anything in /tmp.

Is there something similar to a clipboard for copying and pasting a file?

4
  • 1
    You have to type the cd command, so you can just cd - to go back to the previous directory, up-arrow to recall the cd command, and edit the line to be cp instead of cd. (ctrl-a(beginning-of-line), alt-d (kill-word), cp -a, ctrl-e(end-of-line)). Mar 10, 2016 at 15:40
  • With Emacs and M-x term you can use Emacs' clipboard.
    – Pål GD
    Mar 10, 2016 at 17:56
  • 1
    You can use Midnight Commander and forget about jumping through the hoops. Mar 10, 2016 at 19:29
  • @PålGD People say Emacs' is an operating system... Most have clipboards ;) Mar 13, 2016 at 11:18

9 Answers 9

60

Using Bash, I would just visit the directories:

$ cd /path/to/source/directory
$ cd /path/to/destination/directory

Then, I would use the shortcut ~-, which points to the previous directory:

$ cp -v ~-/file1.txt .
$ cp -v ~-/file2.txt .
$ cp -v ~-/file3.txt .

If one wants to visit directories in reverse order, then:

$ cp -v fileA.txt ~-
$ cp -v fileB.txt ~-
$ cp -v fileC.txt ~-
5
  • 25
    +1 I'm using Unix/Linux shells for more than 20 years now, and I didnt' know that shortcut.
    – Dubu
    Mar 10, 2016 at 11:30
  • 4
    Huh, that is a handy shortcut for "$OLDPWD". Why three separate cp commands, though? cp -a ~-/file[1-3].txt . Mar 10, 2016 at 15:32
  • 4
    Actually, the three cp's are examples. In the real world, wildcard characters can also be used to simplify the copy task. Mar 10, 2016 at 16:39
  • 2
    I was going to mention something about pushd and parsing dirs...but this is far, far better. I suggest you add the fact that "$OLDPWD" is exactly equivalent to ~- and is more portable (helpful for those not using bash.)
    – Wildcard
    Mar 11, 2016 at 5:54
  • 1
    ~+ is likewise a shortcut for "$PWD"
    – Paul Evans
    Mar 12, 2016 at 21:23
11

If I saw that situation coming as a one-off, I might:

a=`pwd`
cd /somewhere/else
cp "$a/myfile" .

If there were directories that I found myself copying files out of semi-regularly, I would probably define some mnemonic variables for them in my .profile.

Edited to add:

After sleeping on it, I wondered how closely I could get to other GUI / OS behaviors where you select some number of files, "cut" or "copy" them, then "paste" them somewhere else. The best selection mechanism I could come up with was your brain/preferences plus the shell's globbing feature. I'm not very creative with naming, but this is the basic idea (in Bash syntax):

function copyfiles {
  _copypastefiles=("$@")
  _copypastesrc="$PWD"
  _copypastemode=copy
}

function cutfiles {
  _copypastefiles=("$@")
  _copypastesrc="$PWD"
  _copypastemode=cut
}

function pastefiles {
  for f in "${_copypastefiles[@]}"
  do
    cp "${_copypastesrc}/$f" .
    if [[ ${_copypastemode} = "cut" ]]
    then
      rm "${_copypastesrc}/$f"
    fi
  done
}

To use it, put the code into ~/.bash_profile, then cd to the source directory and run either copyfiles glob*here or cutfiles glob*here. All that happens is that your shell expands the globs and puts those filenames into an array. You then cd to the destination directory and run pastefiles, which executes a cp command for each source file. If you had previously "cut" the files, then pastefiles also removes the source file (or, tries to). This doesn't do any error-checking (of existing files, before potentially clobbering them with the cp; or that you have permissions to remove the files during a "cut", or that you can re-access the source directory after you move out of it).

1
  • 4
    For your one-off, $OLDPWD already exists, which can be shortened to ~- in bash and zsh. Mar 10, 2016 at 19:50
5

I think the ~- is the right answer, but note that bash has a built-in line editor that can copy/paste text.

If you are in emacs mode you can recall your cd command from the history, and use Control-u to kill the line into the bash "clipboard" called the kill-ring (there are other ways too). You can then yank this string into a new command at any time with Control-y. Obviously, in your example this depends on you having used an absolute directory name in your cd command.

You can also use the interesting default key-binding of Meta-.. This copies the last word from the previous command into your current line. If repeated, each time it goes back one command in the history. So if you do a cd /x, then cd /y followed by cdMeta-.Meta-. you will have /x in your input.

5

Expanding on the answer from Anderson M. Gomes, Bash allows you to refer to any prior directory in your directory stack by typing ~N (or ~+N) where N is the position on the dir stack. For example:

# go some places
$ cd /path/to/source/directory
$ pushd /path/to/destination/directory
$ pushd $HOME
$ pushd /tmp

# show the current dir stack
$ dirs -v
0 /tmp
1 ~
2 /path/to/destination/directory
3 /path/to/source/directory

Now you can copy a file between two past directories, neither of them the current one, with:

cp -v ~3/file1.txt ~2

To solve the original poster's problem, you would do:

$ cd /path/to/source/directory
$ pushd /path/to/destination/directory

# show the current dir stack
$ dirs -v
0 /path/to/destination/directory
1 /path/to/source/directory

# copy
cp -v ~1/file[123].txt .

With a large set of files, you could list their names in a manifest file and then do the copy from the source dir:

$ cd /path/to/destination/directory
$ pushd /path/to/source/directory

# copy
cp -v $(cat files_to_copy.list) ~1

See also: this section of the Bash man page


Similarly, in Tcsh, you can use the =2 notation (rather than ~2) to refer to the second dir on your dir stack.

See also: this section of the Tcsh man page

4

when you are in the first directory, lets say the source or src in short, execute

src=${PWD}

then cd in to second directory and execute:

cp -i ${src}/filename .

the -i option will ask if you want to overwrite, if there is a duplicate file

1
  • Thanks. It is even better without specifying the filename.
    – Tim
    Mar 10, 2016 at 4:14
4

A variation on anderson-m-gomes response. Using Bash, I would just visit the directories:

$ cd /path/to/source/directory
$ cd /path/to/destination/directory

Then, I would use the variable $OLDPWD, which points to the previous directory:

$ cp -v $OLDPWD/file1.txt .

If one wants to visit directories in reverse order, then:

$ cp -v fileA.txt $OLDPWD/
3
  • 3
    +1, but you forgot to "quote" your variable expansions. If $OLDPWD contains spaces, this breaks. Also, I always use cp -a. Also, it's unfortunate that tab-completion is broken on variable expansions. You can use ctrl-alt-e to shell-expand the current command line, though, after typing the $OLDPWD part. Mar 10, 2016 at 15:30
  • 1
    ~- is a shortcut for $OLDPWD Mar 10, 2016 at 19:51
  • I was just pointing out another variation, since Unix/Linux is full of them. Funny, that I've been using Linux for >20 years, and I'd never seen ~- before. Plus, $OLDPWD is easy to remember. Mar 14, 2016 at 17:54
3

If in bash, I would use pushd and popd. These commands keep a handy FIFO stack of directories for later use. You can consult the stack anytime using dirs.

As such I would do:

pushd .
cd /somewhere/else
cp "`popd`/myfile"
0
2

You can use xclip:

NAME
       xclip - command line interface to X selections (clipboard)

SYNOPSIS
       xclip [OPTION] [FILE]...

DESCRIPTION
       Reads  from standard in, or from one or more files, and makes the data available as an X selection for pasting
       into X applications. Prints current X selection to standard out.

Example:

$ cd /path/to/dir1
$ xclip-copyfile file1 file2
$ cd /path/to/dir2
$ xclip-pastefile
file1 file2

Also visit xsel.

1
  • That does a tar | gzip into / out of the X clipboard. Kinda clunky compared to cp, and doesn't generalize to making symlinks or hardlinks. (cp -as or cp -al) Mar 10, 2016 at 15:44
1

You could check out the clipboard-files script here: https://github.com/larspontoppidan/clipboard-files

It provides commands like ccopy, ccut and cpaste that use the desktop environment clipboard and allow intuitive copy / pasting of files:

ccopy myfile
cd <second directory>
cpaste

As the desktop environment clipboard is used, the copy/pasting will interact with the files put on clipboard in other programs like file managers and IDE's. At least it works on Gnome-like desktops.

Full disclosure, I wrote the script after giving up finding something like it out there...

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .