I have a directory structure like what is shown below
foo/
bar/
a.txt
b.py
c.py
and if you do ls -l you would see something like
test#test:/home/foo$ ls -l
lrwxrwxrwx 1 48 Oct 21 12:14 bar -> /lib/python2.7/site-packages/linked_dir/
so the contents of bar/ and linked_dir/ are the same because of the link.
I want to break the link but retain the bar/ directory and its contents. What I have seen online to break a link is rm <link> but that entirely removes the bar/ directory. Is there any way to accomplish what I want?
First copy whatever the symlink points to. By using -L, cp will dereference the symlink:
cp -rL bar new-bar
Delete the symlink:
rm bar
Rename your new copy to the original name:
mv new-bar bar
Related
I am trying to copy a folder having symbolic links to another directory
Note - The actual files i intend to copy are different but just for the purpose of this question to make it easy to demonstrate issue , i am giving a example
xd003#localhost:~$ ls /data/data/com.termux/files/home/source
1.txt 2.txt 3.txt symlink
xd003#localhost:~$
Here's the source folder which has some files and a symbolic link , and the destination folder is empty
xd003#localhost:~$ cp -R /data/data/com.termux/files/home/source /sdcard/dest
cp: cannot create symbolic link '/sdcard/dest/source/symlink': Operation not permitted
xd003#localhost:~$
I copy the source folder to destination directory but i get an error stating the symlink cannot be copied over , just to confirm i check the destination directory and as expected it didn't copied the symbolic file
xd003#localhost:~$ ls /sdcard/dest/source
1.txt 2.txt 3.txt
xd003#localhost:~$
How do i fix this issue and copy the symbolic link in its original state
Edit - After some googling and one answer suggestion below , i tried using cp -LR command .It didn't gave me any error but it copied the symlink as folder and not in its original state , as you can see below the first line itself shows the symlink in destination is copied as a folder and in source , it indeed is a proper symbolic link
xd003#localhost:~$ ls -la /sdcard/dest/source | grep "\->"
xd003#localhost:~$ ls /sdcard/dest/source
1.txt 2.txt 3.txt symlink
xd003#localhost:~$ ls -la /data/data/com.termux/files/home/source | grep "\->"
lrwxrwxrwx. 1 xd003 xd003 13 Jun 12 12:40 symlink -> /sdcard/data/
xd003#localhost:~$
You need to dereference the links:
cp -L -R files/* location/
-L is used to dereference or --dereference
Try these steps:
you zip the entire folder in the original location.
then sudo copy this zip file to the machine where jenkins is running
stop jenkins
sudo unzip -o jenkinslts.zip
now restart jenkins
I want to move file1 to directory1 in many subdirectories of current directory. Both file1 and directory1 are in each subdirectory. I write the following script in current directory but it reports "./mv.sh: line 4: cd: directory1: No such file or directory". Actually, the directory1 is in each subdirectory.
1 #!/bin/bash
2
3 for i in *; do
4 builtin cd $i
5 mv file1 directory1
6 builtin cd ..
7 done
error
./mv.sh: line 4: cd: directory1: No such file or directory
mv: cannot stat `file1': No such file or directory
Is it possible that directory1 is a dangling symbolic link? For example:
mkdir foo
ln -s foo foolink
mv foo bar # foolink still points to foo but foo is gone!
cd foolink
# bash: cd: foolink: No such file or directory
Also, instead of
cd dir
mv foo subdir
cd ..
I would recommend the more succinct, and more importantly, safer version:
mv dir/foo dir/subdir/
Why is this safer? Imagine that dir doesn't exist:
cd dir # Fails
mv foo subdir # Oops! Now we're trying to move a file from the current directory
cd .. # Even bigger oops! Now we're even higher in the directory tree,
# and on the next iteration will be moving files around that we
# shouldn't be
(You could also avert this issue in this particular case by using set -o errexit but in general cd .. in scripts is dangerous, in my opinion.)
Also, as Ansgar Wiechers said, you should use find instead of trying to crawl the tree yourself.
I'd use find rather than trying to crawl the directory tree:
find . -type f -name "file1" -execdir mv {} directory1/ \;
This assumes that each directory with a file file1 has a subdirectory directory1.
I suppose the cd .. in line 6 lead you to another directory. You can check this by inserting builtin pwd between lines 6 and 7. This shows you in which directory you actually are after the cd ...
Maybe one of the directories is in fact a link to another directory? This could be the reason for landing somewhere you did not expect.
If the cd $i fails, you could also land in a wrong directory, this may happen if $i is not a directory or you don't have permission to explore it.
I need to create a zip file using this command:
zip /dir/to/file/newZip /data/to/zip/data.txt
This works, but the created zip file creates a directory structure mimicking the directory to the raw file. It is a lot of extra folders that I don't need.
I didn't find an answer in a cursory glance over the man page or a Google hunt.
You can use -j.
-j
--junk-paths
Store just the name of a saved file (junk the path), and do not
store directory names. By default, zip will store the full path
(relative to the current directory).
Using -j won't work along with the -r option.
So the work-around for it can be this:
cd path/to/parent/dir/;
zip -r complete/path/to/name.zip ./* ;
cd -;
Or in-line version
cd path/to/parent/dir/ && zip -r complete/path/to/name.zip ./* && cd -
you can direct the output to /dev/null if you don't want the cd - output to appear on screen
Use the -j option:
-j Store just the name of a saved file (junk the path), and do not
store directory names. By default, zip will store the full path
(relative to the current path).
Somewhat related - I was looking for a solution to do the same for directories.
Unfortunately the -j option does not work for this :(
Here is a good solution on how to get it done:
https://superuser.com/questions/119649/avoid-unwanted-path-in-zip-file
Alternatively, you could create a temporary symbolic link to your file:
ln -s /data/to/zip/data.txt data.txt
zip /dir/to/file/newZip !$
rm !$
This works also for a directory.
Just use the -jrm option to remove the file and directory
structures
zip -jrm /path/to/file.zip /path/to/file
Retain the parent directory so unzip doesn't spew files everywhere
When zipping directories, keeping the parent directory in the archive will help to avoid littering your current directory when you later unzip the archive file
So to avoid retaining all paths, and since you can't use -j and -r together ( you'll get an error ), you can do this instead:
cd path/to/parent/dir/;
zip -r ../my.zip "../$(basename "$PWD")"
cd -;
The "../$(basename "$PWD")" is the magic that retains the parent directory.
So now unzip my.zip will give a folder containing all your files:
parent-directory
├── file1
├── file2
├── dir1
│ ├── file3
│ ├── file4
Instead of littering the current directory with the unzipped files:
file1
file2
dir1
├── file3
├── file4
I am wondering - how can I move all the files in a directory except those files in a specific directory (as 'mv' does not have a '--exclude' option)?
Lets's assume the dir structure is like,
|parent
|--child1
|--child2
|--grandChild1
|--grandChild2
|--grandChild3
|--grandChild4
|--grandChild5
|--grandChild6
And we need to move files so that it would appear like,
|parent
|--child1
| |--grandChild1
| |--grandChild2
| |--grandChild3
| |--grandChild4
| |--grandChild5
| |--grandChild6
|--child2
In this case, you need to exclude two directories child1 and child2, and move rest of the directories in to child1 directory.
use,
mv !(child1|child2) child1
This will move all of rest of the directories into child1 directory.
Since find does have an exclude option, use find + xargs + mv:
find /source/directory -name ignore-directory-name -prune -print0 | xargs -0 mv --target-directory=/target/directory
Note that this is almost copied from the find man page (I think using mv --target-directory is better than cpio).
First get the names of files and folders and exclude whichever you want:
ls --ignore=file1 --ignore==folder1 --ignore==regular-expression1 ...
Then pass filtered names to mv as the first parameter and the second parameter will be the destination:
mv $(ls --ignore=file1 --ignore==folder1 --ignore==regular-expression1 ...) destination/
This isn't exactly what you asked for, but it might do the job:
mv the-folder-you-want-to-exclude somewhere-outside-of-the-main-tree
mv the-tree where-you-want-it
mv the-excluded-folder original-location
(Essentially, move the excluded folder out of the larger tree to be moved.)
So, if I have a/ and I want to exclude a/b/c/*:
mv a/b/c ../c
mv a final_destination
mkdir -p a/b
mv ../c a/b/c
Or something like that. Otherwise, you might be able to get find to help you.
This will move all files at or below the current directory not in the ./exclude/ directory to /wherever...
find -E . -not -type d -and -not -regex '\./exclude/.*' -exec echo mv {} /wherever \;
ls | grep -v exclude-dir | xargs -t -I '{}' mv {} exclude-dir
rename your directory to make it hidden so the wildcard does not see it:
mv specific_dir .specific_dir
mv * ../other_dir
#!/bin/bash
touch apple banana carrot dog cherry
mkdir fruit
F="apple banana carrot dog cherry"
mv ${F/dog/} fruit
# this removes 'dog' from the list F, so it remains in the
current directory and not moved to 'fruit'
Inspired by #user13747357 's answer.
First you can ls the file and filter them by:
ls | egrep -v '(dir_name|file_name.ext)'
Then you can run the following command to move the files except the specific ones:
mv $(ls | egrep -v '(dir_name|file_name.ext)') target_dir
* Note that I tested this inside a specific directory. Cross-directory operation should be more carefully executed :)
suppose you directory is
.
├── dir1
│ └── a.txt
├── dir2
│ ├── b.txt
│ └── hello.c
├── file1.txt
├── file2.txt
└── file3.txt
and you gonna put file1 file2 file3 into dir2.
you can use
mv $(ls -p | grep -v /) /dir2 to finish it, because
ls -p | grep -v / will print all files except directory in cwd.
For example, if I want to move all files/directories - except a specified file or directory - inside "var/www/html" to a sub-folder named "my_sub_domain", then I use "mv" with the command "!(what_to_exclude)":
$ cd /var/www/html
$ mv !(my_sub_domain) my_sub_domain
To exclude more I use "|" to seperate file/directory names:
$ mv !(my_sub_domain|test1.html) my_sub_domain
mv * exclude-dir
was the perfect solution for me
If I rm -rf a folder that has soft links in it, will it try to follow those links and delete the corresponding folder, or will it simply unlink them?
I have a copy of my home directory with symbolic links in it, and I'm scared to rm -rf it in case it follows those links and blows up the corresponding folders...
Generally speaking, rm doesn't "delete". It "unlinks". This means that references to a file are removed by rm. When the number of references reaches zero, the file will no longer be accessible and in time, the area of disk where it resides will be used for something else.
When you rm a directory, the stuff inside the directory is unlinked. Symbolic links are (sort of like) files with the name of their targets inside them and so they're just removed. To actually figure out what they're pointing to and then unlink the target is special work and so will not be done by a generic tool.
No. rm -rf won't follow symbolic links - it will simply remove them.
% mkdir a
% touch a/foo
% mkdir b
% ln -s a b/a
% rm -rf b
% ls a
foo
Here is axample:
find a b
a
a/1
a/2
b
ll
drwxr-xr-x 2 ****** ****** 4.0K Feb 6 15:11 a
lrwxrwxrwx 1 ****** ****** 1 Feb 6 15:13 b -> a
.
rm -rf b
gives
find a b
a
a/1
a/2
.
rm -rf b/
gives error:
rm: cannot remove `b/': Not a directory
Conclusion:
rm does not follow symlinks
POSIX quote
Since rm -r is POSIX we can also look at what they have to say: https://pubs.opengroup.org/onlinepubs/009604599/utilities/rm.html
The rm utility shall not traverse directories by following symbolic links into other parts of the hierarchy, but shall remove the links themselves.
The rationale section mentions a bit more:
The rm utility removes symbolic links themselves, not the files they refer to, as a consequence of the dependence on the unlink() functionality, per the DESCRIPTION. When removing hierarchies with -r or -R, the prohibition on following symbolic links has to be made explicit.