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?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
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 ~-
Method 2
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=("<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="476307">[email protected]</a>")
_copypastesrc="$PWD"
_copypastemode=copy
}
function cutfiles {
_copypastefiles=("<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="4c680c">[email protected]</a>")
_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).
Method 3
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.
Method 4
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
Method 5
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
Method 6
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/
Method 7
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"
Method 8
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.
Method 9
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…
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0