You are not logged in.
In my PKGBUILD (i.e. bash) file I need to clean a package directory. Basically I have a list of files/directories that I want to preserver and delete everything else. Here is an example of such list:
Rakefile
ext/build/*.a
vendor/foo/include/
I want to delete all the files/directories in "." that do not match any of the the patterns above. A pattern can be path to directory (in this case whole directory shall be preserved) and/or a glob.
I can't find an elegant bash way to do it. Maybe someone can help me?
Last edited by anatolik (2017-01-14 00:53:19)
Read it before posting http://www.catb.org/esr/faqs/smart-questions.html
Ruby gems repository done right https://bbs.archlinux.org/viewtopic.php?id=182729
Fast initramfs generator with security in mind https://wiki.archlinux.org/index.php/Booster
Offline
find . ! -name "Rakefile" ! -path "ext/build/*.a" ! -path "vendor/foo/include/*" -delete
Should work. But replace -delete with -print or similar first to test.
Really the Rakefile could also use a -path option and it'd be fine. If you have a text file list of these matches, you could assemble the find command using -path with each line. If you cannot modify the text file to include an asterisk after directories (e.g., your vendor/foo/include/) you'd need to preprocess the file or each line to append the asterisk to lines ending in /
As an alternative, wouldn't it be possible to do everything in a staging directory (somewhere in srcdir, or in a builddir) then just copy/move the needed files from there to pkgdir. I assume this has been ruled out for some reason, but I can't imagine what would prevent this from being possible.
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
find . ! -name "Rakefile" ! -path "ext/build/*.a" ! -path "vendor/foo/include/*" -delete
This won't work
Note that the pattern match test applies to the whole file name, starting from one of the start points named on the command line.
the -path patterns must be changed to
"*ext/build/*.a" "*vendor/foo/include*"
or, if the target patterns are in the root of the search directory:
"./ext/build/*.a" "./vendor/foo/include*"
Not sure if it's elegant, but there is also the -regex option.
find . ! -regex '.*\(Rakefile\|ext/build/.*\.a\|vendor/foo/include.*\)$' -delete
Offline
Ah, right. But I'd definitely only prepend ./ not * as the later could get a lot of unintended matches where something anything like Rakefile in any subdirectory would also match. The regex approach is probably better, but again not using any prefix, just ./
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
Ah, didn't think about unintended matches enough. Then I would just prepend / , though it becomes a bit unreadable..
find . ! -regex '.*\(/Rakefile\|/ext/build/.*\.a\|/vendor/foo/include.*\)$' -delete
Offline
No, you missed my point, the problem isn't just names like 'fooRakefile' but a file named Rakefile in a subdirectory - you need to get rid of the leading wildcard matching:
$ touch Rakefile
$ mkdir subdir
$ touch subdir/Rakefile
$ find . -regex '.*\(/Rakefile\|/ext/build/.*\.a\|/vendor/foo/include.*\)$' -printf "%p\n"
./subdir/Rakefile
./Rakefile
$ find . -regex '\./\(Rakefile\|ext/build/.*\.a\|vendor/foo/include.*\)$' -printf "%p\n"
./Rakefile
Match against the provided names prepended with a literal "./" not prepended with any wildcard match.
"UNIX is simple and coherent" - Dennis Ritchie; "GNU's Not Unix" - Richard Stallman
Offline
In a script (which you will test and verify), a monster like find delete is probably the way to go.
On interactive shells, I prefer to stick to simple commands, so I invert this problem. Make a new directory, copy the files I want to keep. The old directory can be deleted as a whole, at a later time, when I'm sure I no longer need it.
In a build script (make clean or whatever) I would expect that the files to be deleted are listed explicitely. Otherwise you'd inadvertently remove too much.
For example in a C project you could state to keep *.c *.h but maybe you're editing and the editor has created a #foobar.c# temporarily, or you tried to patch it and thus you have a *.rej file with failed patches, or someone added a readme, or whatever...
It's easy to delete things but hard to make sure you'll never delete too much.
Offline
... the problem isn't just names like 'fooRakefile' but a file named Rakefile in a subdirectory
I thought that was the goal, delete find all files named Rakefile...
edit: same as -name "Rakefile"
Last edited by mis (2017-01-13 17:59:37)
Offline
I thought that was the goal, delete find all files named Rakefile...
In my example above the goal is to match a file called exactly 'Rakefile' and located exactly in the root directory.
Thank you folks for the ideas, let me try to script them.
Read it before posting http://www.catb.org/esr/faqs/smart-questions.html
Ruby gems repository done right https://bbs.archlinux.org/viewtopic.php?id=182729
Fast initramfs generator with security in mind https://wiki.archlinux.org/index.php/Booster
Offline
Using -path and -regexp quickly leads to unreadable command line and requires a lot of text escaping. So I decided what Trilby suggested - just copy files to temp dir and then replace current directory. It works well. Thank you all.
Read it before posting http://www.catb.org/esr/faqs/smart-questions.html
Ruby gems repository done right https://bbs.archlinux.org/viewtopic.php?id=182729
Fast initramfs generator with security in mind https://wiki.archlinux.org/index.php/Booster
Offline