I try to clean release directories when deploying code to the server, but I need to keep at least 5.
Now I use this command to do like I mentioned.
rm -rf $(ls -1t /path/to/deploy/release | tail -n +6)
Everything looks good when I ran this on the server, but It does not work when I try to run via ssh . . .
ssh user#123.456.789.100 'rm -rf $(ls -1t /path/to/deploy/release | tail -n +6)'
Anyone please help or suggest me. What am I do wrong?
Warning: like all things that involve rm -Rf and "should work", the below may actually delete all files on the computer (since ssh is involved, that's both the local and remote computers), and possibly set your kitchen on fire. I take no responsibility for damage etc... Backups (stored somewhere other than your kitchen) are always a good thing to have, and maybe you should test with rm -Ri first?
You don't say what the failure is, but one thing I notice is that the ls command will generate a list of filenames in the /path/to/deploy/release directory, but rm will not be running in that directory, so it's going to try to delete files by those names in your home directory instead of /path/to/deploy/release. This is fairly easy to fix by cding into that directory first (although be sure to write the command so if the cd fails, it won't just randomly delete files in the wrong directory).
Another problem is that the command depends on word splitting to turn the output of ls ... | tail ... into a list of filenames, which will fail if any filenames contain whitespace and/or wildcards. This is trickier to solve, so I'll just ignore the problem and hope it never blows up on you.
Anyway, with the cd fix (and the whitespace bug unfixed), here's what I get:
ssh user#123.456.789.100 'cd /path/to/deploy/release && rm -Rf $(ls -1t | tail -n +6)'
Again, testing with rm -Ri (and having good backups) is recommended.
I have a directory full of sub-directories that look like this:
Track_0000111
Track_0004444
Track_0022222
Track_0333333
Track_5555555
I would like to remove certain directories if they are contained within a list in the file "RemoveFromTop6000_reformatted.txt"
The contents of the text file look like this:
Track_0000111
Track_0022222
Track_0333333
I tried to write a small script to handle this, but it does not seem to work:
#!/bin/bash
for file in cat RemoveFromTop6000_reformatted.txt; do
rm -rfv $file
done
Unfortunately this simply removes the text files, rather than the directories. Any tips?
Thanks!
You forgot backquotes around your call to cat. Without them, rm will simply delete the files cat (which probably doesn't exist, but you might not notice because you're using rm -f) and RemoveFromTop6000_reformatted.txt
Try this:
#!/bin/bash
for file in `cat RemoveFromTop6000_reformatted.txt`; do
rm -rv "$file"
done
or, more simply,
rm -rv `cat $file`
(but this will only work if the directory names don't contain whitespace).
No need to for, for something like this you can do a while read ...; do ... done < file just like this:
#!/bin/bash
while read file
rm -rfv "$file"
done < RemoveFromTop6000_reformatted.txt
you can try below command,
Command:
sed 's/^/"/g' sample.txt | sed 's/$/"/g' | xargs rm -rfv
Description:
Command will remove files as well as directories mentioned in "sample.txt".
NOTE:
In your case,make sure that "RemoveFromTop6000_reformatted.txt"
contains only directories name.
Command will also work if the directories name contains whitespace.
I am not sure why touch filename{1..10} is not working in my k-shell?
Does it necessary to make a loop in this case? If so what is wrong here:
#!/usr/bin/ksh
for i in {1..10}
do
touch file${i}
done
Thanks !!
The original touch file[i] creates a single file with the name "file[i]".
$ touch file[i]
$ ls
file[i]
$
As Sun's older ksh88 dialect does not understand brace expansion, you need to use something like:
i=1 && while ((i<=10)); do
((i+=1))
touch filename${i}
done
I have something like this:
package="com.program.interesting.program.aplication"
I want a script that will create folders like this:
midir com
cd com/
mkdir program
cd program/
...
etc
But I want to do this automatically, no matter how many folder I'll have. I guess this is very simple, but I don't know how to parse a string on the shell and I don't want to read a book, just to solve this.
Thanks
You just need to convert . to / and that is all:
mkdir -p "$(echo $package | tr . /)"
The -p key means that mkdir needs to create all necessary parent directories automatically.
Use "" around the command substitution $() if it is possible that $package can contain spaces inside.
The tr command changes the . symbols in the string to slashes.
e.g.
$ echo com.program.interesting.program.aplication |tr . /
com/program/interesting/program/aplication
mkdir -p com/program/interesting/program/aplication
I have this list of files on a Linux server:
abc.log.2012-03-14
abc.log.2012-03-27
abc.log.2012-03-28
abc.log.2012-03-29
abc.log.2012-03-30
abc.log.2012-04-02
abc.log.2012-04-04
abc.log.2012-04-05
abc.log.2012-04-09
abc.log.2012-04-10
I've been deleting selected log files one by one, using the command rm -rf see below:
rm -rf abc.log.2012-03-14
rm -rf abc.log.2012-03-27
rm -rf abc.log.2012-03-28
Is there another way, so that I can delete the selected files at once?
Bash supports all sorts of wildcards and expansions.
Your exact case would be handled by brace expansion, like so:
$ rm -rf abc.log.2012-03-{14,27,28}
The above would expand to a single command with all three arguments, and be equivalent to typing:
$ rm -rf abc.log.2012-03-14 abc.log.2012-03-27 abc.log.2012-03-28
It's important to note that this expansion is done by the shell, before rm is even loaded.
Use a wildcard (*) to match multiple files.
For example, the command below will delete all files with names beginning with abc.log.2012-03-.
rm -f abc.log.2012-03-*
I'd recommend running ls abc.log.2012-03-* to list the files so that you can see what you are going to delete before running the rm command.
For more details see the Bash man page on filename expansion.
If you want to delete all files whose names match a particular form, a wildcard (glob pattern) is the most straightforward solution. Some examples:
$ rm -f abc.log.* # Remove them all
$ rm -f abc.log.2012* # Remove all logs from 2012
$ rm -f abc.log.2012-0[123]* # Remove all files from the first quarter of 2012
Regular expressions are more powerful than wildcards; you can feed the output of grep to rm -f. For example, if some of the file names start with "abc.log" and some with "ABC.log", grep lets you do a case-insensitive match:
$ rm -f $(ls | grep -i '^abc\.log\.')
This will cause problems if any of the file names contain funny characters, including spaces. Be careful.
When I do this, I run the ls | grep ... command first and check that it produces the output I want -- especially if I'm using rm -f:
$ ls | grep -i '^abc\.log\.'
(check that the list is correct)
$ rm -f $(!!)
where !! expands to the previous command. Or I can type up-arrow or Ctrl-P and edit the previous line to add the rm -f command.
This assumes you're using the bash shell. Some other shells, particularly csh and tcsh and some older sh-derived shells, may not support the $(...) syntax. You can use the equivalent backtick syntax:
$ rm -f `ls | grep -i '^abc\.log\.'`
The $(...) syntax is easier to read, and if you're really ambitious it can be nested.
Finally, if the subset of files you want to delete can't be easily expressed with a regular expression, a trick I often use is to list the files to a temporary text file, then edit it:
$ ls > list
$ vi list # Use your favorite text editor
I can then edit the list file manually, leaving only the files I want to remove, and then:
$ rm -f $(<list)
or
$ rm -f `cat list`
(Again, this assumes none of the file names contain funny characters, particularly spaces.)
Or, when editing the list file, I can add rm -f to the beginning of each line and then:
$ . ./list
or
$ source ./list
Editing the file is also an opportunity to add quotes where necessary, for example changing rm -f foo bar to rm -f 'foo bar' .
Just use multiline selection in sublime to combine all of the files into a single line and add a space between each file name and then add rm at the beginning of the list. This is mostly useful when there isn't a pattern in the filenames you want to delete.
[$]> rm abc.log.2012-03-14 abc.log.2012-03-27 abc.log.2012-03-28 abc.log.2012-03-29 abc.log.2012-03-30 abc.log.2012-04-02 abc.log.2012-04-04 abc.log.2012-04-05 abc.log.2012-04-09 abc.log.2012-04-10
A wild card would work nicely for this, although to be safe it would be best to make the use of the wild card as minimal as possible, so something along the lines of this:
rm -rf abc.log.2012-*
Although from the looks of it, are those just single files? The recursive option should not be necessary if none of those items are directories, so best to not use that, just for safety.
I am not a linux guru, but I believe you want to pipe your list of output files to xargs rm -rf. I have used something like this in the past with good results. Test on a sample directory first!
EDIT - I might have misunderstood, based on the other answers that are appearing. If you can use wildcards, great. I assumed that your original list that you displayed was generated by a program to give you your "selection", so I thought piping to xargs would be the way to go.
if you want to delete all files that belong to a directory at once.
For example:
your Directory name is "log" and "log" directory include abc.log.2012-03-14, abc.log.2012-03-15,... etc files. You have to be above the log directory and:
rm -rf /log/*