copying files from etc ending with digit to test1 directory - linux

I'm new to linux and as an exercice I need to copy the "etc" files that end with a digit from home directory to the test1 directory
(with one command).
I tried this but it dosn't work
find /etc -type f -iname "*[3-9]" -exec cp {} ../test1/ \;

this should work for your home directory files ending with digit
mv `ls . |grep -Eo "^.*[0-9]$"` your-directory
lets says in the current directory you have some files like ofjweifhwef9 or kfhiofeh8 ( files ending with digit)
so ls will list them.
this grep expression "^.*[0-9]$"` will find only files ending with digit. ( because in your home directory system wont allow to have a file like this "/etc/somefile123")
and then mv will move those files to your-directory
note :- if grep cannot find the files ending with number you will see an error ofcourse because mv needs 2 operands but since it wasn't there so error.
mv: missing destination file operand after './your-directory'

It is probably because /etc is a link in the system that you're using, and find doesn't seem to consider it a path until you add an extra / at the end. Try this instead:
find /etc/ -type f -iname "*[3-9]" -exec cp {} ../test1/ \;
Notice the /etc/ instead of /etc. I get the same behavior on my Mac where /etc is a link to another directory.
Of course, also make sure that you have files which names end on a digit under the /etc/ directory tree. I have none in my mac. You should get some files when you run:
find /etc/ -type f -iname "*[3-9]"
If you don't, you don't have any files to copy. You may also try: find /etc/ to see all files under the directory tree.
Finally, you may want to add the option: -depth 1 if you only want to copy the files in the /etc/ directory, as opposed to all the files that match in the directory tree under /etc/.

Related

Current directory after was moved by another user

I have a terminal which is opened on a folder a:
hostname:/path/to> mkdir a
hostname:/path/to> cd a
hostname:/path/to/a> cat > b.txt
Another user has moved the folder to another location
hostname:/path/to> mv a /another/hidden/path/i/dont/know
I would like to know where he moved it.
The old terminal still works, but pwd shows the old path because the way that the linux file system works. Old absolute path not exists of course:
hostname:/path/to/a> ls
b.txt
hostname:/path/to/a> pwd
/path/to/a
hostname:/path/to/a> ls /path/to/a
ls: cannot access /path/to/a: No such file or directory
I thought about traversing the upper hierarchy and look for the correct folder in each level:
hostname:/path/to/a> ls ../
...
hostname:/path/to/a> ls ../../
...
hostname:/path/to/a> ls ../../../
...
However this solution may be very hard if one of the levels contain a lot of subdirectories. In my specific case it is not possible as I don't have permissions in one of the upper levels.
I guess it may be impossible to find the exact path, because of the way that linux fs works (e.g. there may be a lot of hard-links for the same directory). I don't care to get some candidates for the path, is there a way to find an absolute path which enables me to approach the directory?
You can try find / -d -name "a" -exec cd {} \; to change to the moved directory, assuming that the user didn't change it's name. If you would like to get the path to the moved directory use find / -d -name "a" -exec echo "path is {}" \;
EDIT
If there are more directories with the same name and you know when the dir was moved, use find / -d -name "a" -mmin -$minutes -exec echo "path is {}" \; where $minutes is the time it was changed at to find all dirs name "a" changed in the specified time period.
If someone renamed and moved the diretory, you need to do some manual work. Use find / -d -mmin -$minutes -ls to list all dirs changed within the specified time period.
As hellerpop says, you might want to use -cmin instead of -mmin
Answering my own question: I may use lsof on a uniquely-named subfolder (I should traverse into it so it is considered as "opened"):
hostname:/path/to/a> mkdir uniquely_named_directory
hostname:/path/to/a> cd uniquely_named_directory
hostname:/path/to/a/uniquely_named_directory> lsof | grep uniquely_named_directory
It can be done only if I have such folder or have write permissions to the folder. Alternatively, if I know that the folder was not renamed and has a name which is special enough, I may simply try "lsof | grep a".
(Based on idea suggested here in a deleted answer...).

Newbie-ish error: cp: omitting directory

Pulling my hair as I'm stuck with a basic error without understanding why:
find . -type f -exec cp del {} \;
We're in a "test" directory, in which I created one "del" subdirectory. The "test" directory contains a variety of files of various types.
The result is a series of lines (same number as the number of files present in the directory from where the command is ran) with:
cp: omitting directory `del'
Possibly useful details follow.
Debian Wheezy, standard shell interface.
As a prelude to more complex exclusion and exec patterns I wanted to start with this fundamental test... and had this.
I think I excluded the "del" directory with "type -f", so it's not as if I was asking Linux to move a directory within itself.
There are no other directories or subdirectories.
Permissions: everything belongs to the current user.
I made variations for the "cp del" part, putting it in simple or double quotes, or using ./del, no difference.
I also tried with -R
find . -type f -name '*script1*' -exec cp -R ./del {} \;
That gave:
cp: cannot overwrite non-directory `./script1' with directory `./del'
Same with -r
If what you're trying to do is to copy some files found by find command to the del directory, then you can do it like this:
find . -type f | xargs cp -T del/
Or like this:
find . -type f -exec cp {} del \;

Get list of files that contain given text within directory given by pattern

I want to get a list of files that contain a given text within my file-system. Furthermore only files should be considdered that are located in a directoy given by a pattern.
So let´s say I have a number of directories called myDir within my filelsystem as shown here:
/usr
/myDir
/tmp
/myDir
/anotherDir
Now I want to get all the files within those directories that contain the text.
So basically I need to perform these steps:
loop all directories names myDir on the whole file-system
for every directory within that list get the files that contain the search-string
What I tried so far is find /etc /opt /tmp /usr /var -iname myDir -type d -exec ls -exec grep -l "SearchString" {} \;
However this doesn´t work as the results of find are directories which I may not use as input for grep. I assume I have to do one step in between the find and the grep but can´t find out how to do this.
I think I got it and will show you a little script that achieves what I need:
for i in $(find / -type d -iname myDir) do
for j in $(find "$i" -type f) do
grep "SearchString" "$j"
done
done
This will give me all the files that contain the SearchString and are located in any of the folders named myDir.

linux cp: how to have it follow links but not stop if a link target doesn't exist

I want to recursively copy a dir and have the targets of the links copied, but I do not want the cp to stop if a target of a link does not exist.
For example, I run this command:
cp -fprL /path/to/src_dir /path/to_dest_dir
But the first time it hits symlink where the target doesn't exist it exits:
cp: cannot stat `/path/to/non-existent/file': No such file or directory
Is there some way to get cp to silently skip these and continue on?
With the standard GNU toolchain, no, there's no way.
You could instead copy your files, keeping symlinks as symlinks, then use find -follow -type l -delete to delete the broken symlinks, and then copy again, this time following symlinks.
Of course, you could also just write a python etc. program to do the copy for you, or find all files in the original trees that are not broken symlinks and use these with cp, replacing parts of the path with the target path using sed:
find -type d|sed 's/^\(.*\)/"\1" "\/target\/\1"/g'|xargs -p mkdir
find -follow -not -type l -not -type d|sed 's/^\(.*\)/"\1" "\/target\/\1"/g'|xargs -n2 cp
sed will duplicate your found file path, prefixing it with the target directory.

How to change all occurrences of a word in all files in a directory

I was in the process of creating a User class where one of the methods was get_privileges();.
After hours of slamming my head into the keyboard, I finally discovered that the previous coder who I inherited this particular database spelled the word "privileges" as "privelages" in the MySQL database, and thus also everywhere in the hundreds of files that access these "privelages" it is spelled that way.
Is there a way in Linux (Ubuntu Server) that I can go through every place in the /var/www folder and replace "privelages" with "privileges", so that I don't have to deal with this typo and code around it?
A variation that takes into account subdirectories (untested):
find /var/www -type f -exec sed -i 's/privelages/privileges/g' {} \;
This will find all files (not directories, specified by -type f) under /var/www, and perform a sed command to replace "privelages" with "privileges" on each file it finds.
Check this out: http://www.cyberciti.biz/faq/unix-linux-replace-string-words-in-many-files/
cd /var/www
sed -i 's/privelages/privileges/g' *
I generally use this short script, which will rename a string in all files and all directory names and filenames. To use it, you can copy the text below into a file called replace_string, run sudo chmod u+x replace_string and then move it into your sudo mv replace_string /usr/local/bin folder to be able to execute it in any directory.
NOTE: this only works on linux (tested on ubuntu), and fails on MacOS. Also be careful with this because it can mess up things like git files. I haven't tested it on binaries either.
#!/usr/bin/env bash
# This will replace all instances of a string in folder names, filenames,
# and within files. Sometimes you have to run it twice, if directory names change.
# Example usage:
# replace_string apple banana
echo $1
echo $2
find ./ -type f -exec sed -i -e "s/$1/$2/g" {} \; # rename within files
find ./ -type d -exec rename "s/$1/$2/g" {} \; # rename directories
find ./ -type f -exec rename "s/$1/$2/g" {} \; # rename files

Resources