25

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?

  • 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)). – Peter Cordes Mar 10 '16 at 15:40
  • With Emacs and M-x term you can use Emacs' clipboard. – Pål GD Mar 10 '16 at 17:56
  • 1
    You can use Midnight Commander and forget about jumping through the hoops. – Deer Hunter Mar 10 '16 at 19:29
  • @PålGD People say Emacs' is an operating system... Most have clipboards ;) – Volker Siegel Mar 13 '16 at 11:18
  • @JeffSchaller thanks................................ – Tim May 13 '17 at 14:58
59

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 ~-
  • 25
    +1 I'm using Unix/Linux shells for more than 20 years now, and I didnt' know that shortcut. – Dubu Mar 10 '16 at 11:30
  • 4
    Huh, that is a handy shortcut for "$OLDPWD". Why three separate cp commands, though? cp -a ~-/file[1-3].txt . – Peter Cordes Mar 10 '16 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. – Anderson M. Gomes Mar 10 '16 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 '16 at 5:54
  • 1
    ~+ is likewise a shortcut for "$PWD" – Paul Evans Mar 12 '16 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).

  • 4
    For your one-off, $OLDPWD already exists, which can be shortened to ~- in bash and zsh. – Gilles Mar 10 '16 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

  • Thanks. It is even better without specifying the filename. – Tim Mar 10 '16 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
    +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. – Peter Cordes Mar 10 '16 at 15:30
  • 1
    ~- is a shortcut for $OLDPWD – Gilles Mar 10 '16 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. – Scott Carlson Mar 14 '16 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"
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.

  • 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) – Peter Cordes Mar 10 '16 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...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.