Chmod recursively - linux

I have an archive, which is archived by someone else, and I want to automatically, after I download it, to change a branch of the file system within the extracted files to gain read access. (I can't change how archive is created).
I've looked into this thread: chmod: How to recursively add execute permissions only to files which already have execute permission as into some others, but no joy.
The directories originally come with multiple but all wrong flags, they may appear as:
drwx------
d---r-x---
drwxrwxr-x
dr--r-xr--
Those are just the few I've discovered so far, but could be more.
find errors when tries to look into a directory with no x permission, and so doesn't pass it to chmod. What I've been doing so far, is manually change permissions on the parent directory, then go into the child directories and do the same for them and so on. But this is a lot of hand labour. Isn't there some way to do this automatically?
I.e. how I am doing it now:
do:
$ chmod -R +x
$ chmod -R +r
until I get no errors, then
$ find -type f -exec chmod -x {} +
But there must be a better way.

You can use chmod with the X mode letter (the capital X) to set the executable flag only for directories.
In the example below the executable flag is cleared and then set for all directories recursively:
~$ mkdir foo
~$ mkdir foo/bar
~$ mkdir foo/baz
~$ touch foo/x
~$ touch foo/y
~$ chmod -R go-X foo
~$ ls -l foo
total 8
drwxrw-r-- 2 wq wq 4096 Nov 14 15:31 bar
drwxrw-r-- 2 wq wq 4096 Nov 14 15:31 baz
-rw-rw-r-- 1 wq wq 0 Nov 14 15:31 x
-rw-rw-r-- 1 wq wq 0 Nov 14 15:31 y
~$ chmod -R go+X foo
~$ ls -l foo
total 8
drwxrwxr-x 2 wq wq 4096 Nov 14 15:31 bar
drwxrwxr-x 2 wq wq 4096 Nov 14 15:31 baz
-rw-rw-r-- 1 wq wq 0 Nov 14 15:31 x
-rw-rw-r-- 1 wq wq 0 Nov 14 15:31 y
A bit of explaination:
chmod -x foo - clear the eXecutable flag for foo
chmod +x foo - set the eXecutable flag for foo
chmod go+x foo - same as above, but set the flag only for Group and Other users, don't touch the User (owner) permission
chmod go+X foo - same as above, but apply only to directories, don't touch files
chmod -R go+X foo - same as above, but do this Recursively for all subdirectories of foo

You need read access, in addition to execute access, to list a directory. If you only have execute access, then you can find out the names of entries in the directory, but no other information (not even types, so you don't know which of the entries are subdirectories). This works for me:
find . -type d -exec chmod +rx {} \;

Try to change all the persmissions at the same time:
chmod -R +xr

To make everything writable by the owner, read/execute by the group, and world executable:
chmod -R 0755
To make everything wide open:
chmod -R 0777

Adding executable permissions, recursively, to all files (not folders) within the current folder with sh extension:
find . -name '*.sh' -type f | xargs chmod +x
* Notice the pipe (|)

Give 0777 to all files and directories starting from the current path :
chmod -R 0777 ./

Related

setuid on echo command but not working as expected

I have a question about setuid:
for example, there is a file - 1.txt, only root has write permission:
$ll 1.txt
-rw-r--r--. 1 root root 57 Jul 1 12:19 1.txt
For an ordinary user to modify the file, I did the following:
$ sudo chmod u+s /usr/bin/echo
$ ll /usr/bin/echo
-rwsr-xr-x. 1 root root 33128 Oct 31 2018 /usr/bin/echo
However, when the user ran below command, it still got permission error.
$ echo 111 > 1.txt
bash: 1.txt: Permission denied
Then I did a similar test on ls command:
Only root has write permission to test/ directory:
$ ll -d test/
drw-------. 2 root root 34 Jul 1 14:18 test/
a user that run ls command would report an error
$ ls test/
ls: cannot open directory test/: Permission denied
Then setuid on ls command:
$ sudo chmod u+s /usr/bin/ls
$ ll /usr/bin/ls
-rwsr-xr-x. 1 root root 117680 Oct 31 2018 /usr/bin/ls
after this, the user was able to run the command
$ ls test/
1 23 4
What's the difference between echo and ls? Or what I missed here?

Why find piped to xargs mv deleted my files?

Today I experienced something unbelievable. My goal was to mv files newer than 7 days to another directory. The directory exist.
I used command:
find ./* -newermt $(date +%Y-%m-%d -d '7 day ago') -type f -print | xargs -I '{}' mv {} ../update_error_handled
Then, unbelievably the files were gone, I went to the folder used ls -lA and didn't found any files I moved. What happened? CentOS 7.0, there were no directory mount, original files missing, tried to grep -r "content" / - found nothing... .
So why it did behave that way?
Beforehand I launched
find ./* -newermt $(date +%Y-%m-%d -d '7 day ago') -type f -print it returned:
./file66.xml
./file67.xml
...etc.
It really do sucks to lose data in such a way.
To clarify: Directory existed before moving files. Directory does not contain my files I tried to move today, only older ones.
Did you create in advance a directory at ../update_error_handled?
If not, then all that you have left from the files will be the last one, which will be called ../update_error_handled.
In order to avoid such mistakes, I always make sure that the destination directory exists, by adding /. at the end of the destination directory name.
Unsafe approach:
$ rm -rf file dest_dir
$ touch file
$ ls -ld file dest_dir
ls: cannot access 'dest_dir': No such file or directory
-rw-rw-r--. 1 u u 0 Sep 28 11:53 file
$ mv file dest_dir
$ ls -ld file dest_dir
ls: cannot access 'file': No such file or directory
-rw-rw-r--. 1 u u 0 Sep 28 11:53 dest_dir
Using the unsafe approach, file was renamed to a file named dest_dir.
Safe approach:
$ rm -rf file dest_dir
$ touch file
$ ls -ld file dest_dir
ls: cannot access 'dest_dir': No such file or directory
-rw-rw-r--. 1 u u 0 Sep 28 11:54 file
$ mv file dest_dir/.
mv: cannot move 'file' to 'dest_dir/.': No such file or directory
$ ls -ld file dest_dir
ls: cannot access 'dest_dir': No such file or directory
-rw-rw-r--. 1 u u 0 Sep 28 11:54 file
Using the safe approach, the mv command failed and the file file remained intact.

LINUX: How to softlink specific files in all subdirectories

I want to create soft links (ln -s) to folder2 of all the files that contain *foo* in its name, and can be found in some or all the subdirectories of folder1.
I've tried it with for, find, and find -exec ln, and a combination of them, but all I get is a broken link named *foo* or a link to everything inside folder1
With globstar at one stroke.
shopt -s globstar
cd folder2
ln -s ../folder1/**/*foo* .
cd is needed for relative links (this applies for below answers that utilizes find too). If you want absolute links, do
shopt -s globstar
ln -s /where/is/it/folder1/**/*foo* folder2/
If you're in the target folder you want to create the symbolic link, just use ln -s <target file>. The sym link name will be same as the target file.
If you need to do this for several file, use a for loop.
Example:
$ mkdir folder1 folder2
$ cd folder1
$ touch foo foobar foofoobar foobarfoo bar barfoo barbar
$ ls
bar barbar barfoo foo foobar foobarfoo foofoobar
$ cd ../folder2
$ for i in ../folder1/*foo*; do ln -s $i; done
$ ls -l
total 0
lrwxrwxrwx 1 abc abc 17 oct. 26 11:57 barfoo -> ../folder1/barfoo
lrwxrwxrwx 1 abc abc 14 oct. 26 11:57 foo -> ../folder1/foo
lrwxrwxrwx 1 abc abc 17 oct. 26 11:57 foobar -> ../folder1/foobar
lrwxrwxrwx 1 abc abc 20 oct. 26 11:57 foobarfoo -> ../folder1/foobarfoo
lrwxrwxrwx 1 abc abc 20 oct. 26 11:57 foofoobar -> ../folder1/foofoobar
Try this,
for fileName in `find folder1 -name *foo*`
do
name1=`basename $fileName`
ln -sf $fileName folder/$name1
done
Check this
for file in `find . -name *foo* -print`
do
ln -s $file folder2/
done

Subdirectory not created with proper group even parent has SGID

I have a folder with the SGID bit on:
lucas#arturito:/home$ ls -l | grep share
drwxrwsr-x 11 share sambashare 4096 May 5 14:54 share
If I move into share an I create a folder within it, that folder will have the group 'sambashare'. So far, so good...
lucas#arturito:/home$ cd share/
lucas#arturito:/home/share$ mkdir test
lucas#arturito:/home/share$ ls -l | grep test
drwxrwsr-x 2 lucas sambashare 4096 May 5 15:07 test
Now, if I move under /home/share/test and create a new folder, that new folder inherits the group: SGID is working.
lucas#arturito:/home/share$ cd test
lucas#arturito:/home/share/test$ mkdir test1
lucas#arturito:/home/share/test$ ls -l | grep test1
drwxrwsr-x 2 lucas sambashare 4096 May 5 15:09 test1
However, under /home/share I do have other folders other than the newly created 'test'. If I move under any of those, and create a new folder (say 'test2'), that new folder will ignore the SGID and the group will be my group.
lucas#arturito:/home/share$ ls -l | grep 99
drwxrwxr-x 9 share sambashare 4096 May 5 15:11 99_varios
lucas#arturito:/home/share$ cd 99_varios/
lucas#arturito:/home/share/99_varios$ mkdir test2
lucas#arturito:/home/share/99_varios$ ls -l | grep test2
drwxrwxr-x 2 lucas lucas 4096 May 5 15:11 test2
Why is that happening? Isn't it enough for /home/share to have g+s for any other directory below it (new or old) to inherit /home/share's group?
I'm lost. Any hint or idea will be highly appreciated!
Thanks!
Lucas
New folders will inherit the bit but existing ones need to have it set explicitly. You can run the command below once to recursively set it on any existing subfolders.
find /home/share -type d -exec chmod g+s '{}' \;

Why can I remove file without user permission?

I made small test to check how permissions work:
test#comp ~/Documents $ touch test1
test#comp ~/Documents $ ls -l
-rw-r--r-- 1 test test 0 Jul 24 22:14 test1
test#comp ~/Documents $ chmod 044 test1
test#comp ~/Documents $ ls -l
----r--r-- 1 test test 0 Jul 24 22:14 test1
test#comp ~/Documents $ cat test1
cat: test1: Permission denied
test#comp ~/Documents $ rm test1
rm: remove write-protected regular empty file ‘test1’? y
test#comp ~/Documents $ ls -l
total 0
My question is, why when I have no permission on user I can't read file but I can remove it?
In order to remove the file one needs a write permission on the directory that contains this file.
For more information: http://linuxcommand.org/lts0070.php

Resources