zsh delete subdirectory with wildcard in path - wildcard

For a directory structure of:
└── bar
├── first
│   └── tmp
└── second
└── tmp
I want to delete all tmp directories.
However,
rm -rf 'bar/*/tmp/'
does not delete the directory
ls bar/*/
still retrurns both tmp directories:
bar/first/:
tmp
bar/second/:
tmp

your problem here is the single quotes
rm -rf 'bar/*/tmp/'
if you remove them you'll be fine.
rm -rf bar/*/tmp
The reason for this is that single quotes in (most, if not all) shell languages indicates that the contained string of characters is to be treated entirely as a string, which ignores the globbing you are trying to do.

Related

rsync include specific files and exclude directory

I have a directory structure as below:
base
├── config.yml
├── build
│ └── output.yml
│ └── <multiple level sub-directories each having many files including *.c and *.h files>
├── <source directories - having many sub-directories with various files including *.c and *.h files>
│ ├── <xyz>
| │ ├── <x1>
| │ .
│ | └── <xy>
│ .
│ .
│ └── <abc>
├── <more directories, each having multiple files including *.c and *.h files>
I need to sync this directory to remote, but I only need *.c and *.h files. Also complete 'build' directory needs to be excluded. I am running below command:
rsync -avm --include '*/' --include='*.c' --include='*.h' --exclude='*' base "$target_loc"
This is syncing all *.c and *.h files which is desired but it also syncs *.c and *.h files from build and its sub directories
I tried
rsync -avm --include '*/' --include='*.c' --include='*.h' --exclude='build' --exclude='*' base "$target_loc". It still syncs files from build and it's sub directories.
How can I fix this?
You need to put --exclude='build' before --include '*/'. Both of these rules could apply to the "build" directory, and whichever is given first takes precedence, so to get the --exclude rule to override the --include rule, you need to list it first.
From the rsync man page, in the FILTER RULES section (with my emphasis):
As the list of files/directories to transfer is built, rsync checks
each name to be transferred against the list of include/exclude
patterns in turn, and the first matching pattern is acted on: if it is
an exclude pattern, then that file is skipped; if it is an include
pattern then that filename is not skipped; if no matching pattern is
found, then the filename is not skipped.

How to compile multiple simple projects with GNU make

I am trying to implement various project from a programming book. My intention was to have each project exercise in its own folder and then have a makefile that compiles all of them with something like a make all. The folder structure is like this:
.
├── Makefile
├── bin
│   ├── prog1
│ ├── prog2
│ └── prog3
└── src
├── prog1
│ ├── Makefile
│ └── main.c
├── prog2
│ ├── Makefile
│ └── main.c
└── prog3
├── Makefile
└── main.c
I would like to learn how to set up such a structure. In particular the part where the top makefile visit all folders in src calls make there, and then copies and renames the executable into the bin folders.
Your layout schematic shows a makefile for each exercise, plus the top-level makefile that you seem actually to be asking about. It would be best for the top-level makefile to avoid duplicating the behavior of the per-exercise makefiles, as such duplication would create an additional maintenance burden for you. Additionally, it is likely that you will eventually progress to exercises involving multiple source files, and perhaps to some that have multiple artifacts to be built. This is all the more reason for each per-exercise makefile to contain everything necessary to build the exercise with which it is associated (into the exercise-specific directory), and for the top-level makefile to depend on those.
Following that scheme would leave a well-defined role for the top-level makefile: to perform the per-exercise builds (by recursively running make), and to copy the resulting binaries to bin/. This is not the only way to set up a system of cooperating makefiles, but it is fairly easy, and that will allow you to focus on the exercises instead of on the build system.
Let us suppose, then, that each individual exercise can be built by changing to its directory and running make, with the result being an executable in the same directory, with the same name as the directory. That is, from the top-level directory, executing cd src/prog2; make would produce the wanted executable as src/prog2/prog2. In that case, the top-level makefile needs little more than the names of all the exercises, and a couple of rules:
EXERCISES = prog1 prog2 prog3
BINARIES = $(EXERCISES:%=bin/%)
all: $(BINARIES)
$(BINARIES):
make -C src/$$(basename $#)
cp src/$$(basename $#)/$$(basename $#) $#
Note: that uses a feature specific to GNU's implementation of make to compute the names of the wanted binaries from the exercise names. I take that to be acceptable, since you tagged [gnu-make], but in any case, it is a convenience feature, not a necessity.
There are different ways to tackle this, but something like this should work for your example:
PROGS := bin/prog1 bin/prog2 bin/prog3
all: $(PROGS)
$(PROGS):
$(MAKE) -C src/$(#F)
mkdir -p $(#D)
cp src/$(#F)/main $#
.PHONY: clean
clean:
rm -f $(PROGS)
for t in $(PROGS); do make -C src/`basename $$t` clean; done
We define a list of targets (PROGS) we are to build. We say these targets are prerequisites of all and then we go ahead and define how they should be built, that is: we recursively descent into src/ plus filename part of the target to run make there. We create directory of the target to be sure it's there and copy main from the directory we've descended to the path of the target.
For a good measure, there is a clean target as well that removes all the PROGS and runs make clean recursively in src/.

R-Markdown's render_site function is deleting the contents of the .git folder

Im trying to version control a website generated with R-Markdown's render_site function by pushing it directly from the output directory, the default _site folder. Problem is, every time i call the render_site function it clears most of the content of the .git folder (save for the objects folder within) and breaks the link between the local and remote directory. Is there any way to stop this from happening? Curiously, the clean_site function clears the exact same folders and files from the .git folder so im guessing the problem is related to some post build cleanup.
The webpage directory looks something like this:
_site/
├── /.git
├── /index_files
├── /about_files
├── intex.html
├── about.html
└── styles.css
The .git folder before rendering the site looks like:
.git/
├── /hooks
├── /info
├── /logs
├── /objects
├── /refs
├── COMMIT_EDITMSG
├── config
├── description
├── FETCH_HEAD
├── HEAD
└── index
And after building only the objects folder is left:
.git/
└── /objects
I should also note that rendering each .Rmd file into htmls individually does not cause the same problem.
The default clean function for the site generator doesn't exclude anything. You can replace it fairly easily, using a scheme something like this:
Choose a name for your new generator, and put it in the YAML for the index.Rmd file, e.g.
site: my_site
Write my_site to modify the default generator (or the original custom one,
if you already had one):
my_site <- function(...) {
site <- rmarkdown:::default_site(...) # or bookdown::bookdown_site(...), etc.
# Modify the clean function
oldclean <- site$clean
site$clean <- function(...) {
files <- oldclean(...)
# leave out any filename containing .git
grep("[.]git", files, value = TRUE, invert = TRUE)
}
site
}
I haven't tested this and might have the pattern wrong in the new clean function, but it should be close to working.
You might also want to suggest to the rmarkdown authors (on their Github site) that it would be nice to have a way to mark certain files to exclude from cleaning.

How to tar all files in current directory using tar but without inputing names of tar file and all files?

ENV:
macOS Sierra 10.12.6
Raw input(example):
.
├── f1.md
├── f2.md
├── f3.md
├── f4.txt
├── f5.csv
└── f6.doc
0 directories, 6 files
In a test folder, there are 6 files.
Expected output:
.
├── all.tar
├── f1.md
├── f2.md
├── f3.md
├── f4.txt
├── f5.csv
└── f6.doc
0 directories, 7 files
Trying and Problem
tar -cvf all.tar f1.md f2.md f3.md f4.txt f5.csv f6.doc
Though I get the result from the above method but I have to inputing all file names and the compressed file name, which is inconvenient. For example , I can select all files and right click, then choose compressed option without inputing all.tar (I don't mind the .tar filenames.)
Hope
command-line method without inputing specific file names.
In case you want all files, including those in the subdirectories (or if you have no subdirectories), you would run:
tar -cvf all.tar *
Then, bash would expand * into the list of all files in the current directory, including subdirectories.
In case you want only those files in the current directory, but NOT in the subdirectories, then you would have to use find, in a more complicated command. Let me know if this is the case for you, and I can take the time to find that combination of commands for you.

How do I tar node modules in different directories?

I want to cache node modules for each submodule. How can I do so? For example I have the following directory structure:
/test1/node_modules
/test2/node_modules
How do I tar each node module directory under the main directory so that I can then have a zip file with the following structure
/test1/node_modules
/test2/node_modules
edit
What I mean is that I want to get all the node_modules directories under the main directory. node_modules directory can be under directory test1 or test2 or test3. I want to get them all and zip them, maintaining the directory structure. So in the zip file they will be test1/node_modules, test2/node_modules
... but I also want a "catch all" solution... every node_modules dir should be in my tar.
Its not clear where you're blocked. Here is how I would do it:
Use 2 distinct commands, one to create, one to add:
# create my.tar
tar cf my.tar /test1/node_modules/*
# add second directory with tar uf
tar uf my.tar /test2/node_modules/*
If you have more than test1 & test2, but want to have all test dirs:
tar cf my.tar /test*/node_modules/
If you want every node_modules, then use a find command, piped to your tar command
find / -type d -name node_modules | xargs tar cf my.tar
Assume you have these node_modules
➦ tree ./
./
├── pack.js
├── test1
│   └── node_modules
│   └── a
└── test2
└── node_modules
└── b
4 directories, 3 files
You can use node script to pack files. /^test\d+/ means test1 test2 test3 etc.
'use strict';
const fstream = require('fstream');
const zlib = require('zlib');
const tar = require('tar');
const path = require('path');
const dist = path.join(__dirname, 'all.tgz');
fstream.Reader({
path: __dirname,
filter() {
return this.path === __dirname ||
path.relative(__dirname, this.path).match(/^test\d+/);
},
})
.pipe(tar.Pack({ fromBase: true }))
.pipe(zlib.createGzip())
.pipe(fstream.Writer(dist));
Run node pack.js and all node_modules directories will be in one file all.tgz.
vim all.tgz
" tar.vim version v29
" Browsing tarfile
" Select a file with cursor and press ENTER
/
test1/
test1/node_modules/
test1/node_modules/a
test2/
test2/node_modules/
test2/node_modules/b

Resources