me#s:/tmp$ mkdir -p test/raw test/{a,b,c}/data/x
me#s:/tmp$ tree test/
test/
├── a
│ └── data
│ └── x
├── b
│ └── data
│ └── x
├── c
│ └── data
│ └── x
└── raw
I need to exclude test/raw and test/b/data but tree -I only want folder names:
me#s:/tmp$ tree test -I 'raw|b/data'
test
├── a
│ └── data
│ └── x
├── b
│ └── data
│ └── x
└── c
└── data
└── x
Without the b/data that exclude all data folders:
me#s:/tmp$ tree test -I 'raw|data'
test
├── a
├── b
└── c
me#s:/tmp$
The options -P and -I of the tree command, only work on the file-names and not on the path-names of the file [1].
Having hat said, you could use grep to extract the wanted information:
$ tree -f test | grep -vE '(raw|b/data)'
test
├── test/a
│ └── test/a/data
│ └── test/a/data/x
├── test/c
│ └── test/c/data
│ └── test/c/data/x
Here, we make use of the flag -f which prints the relative path-name with respect to the directory test. The grep command does the rest.
As you notice, the exclusion of raw does not allow for a clean tree-output as you have spurious |'s .
Notes:
in Linux, everything is a file.
As of the current version of tree (v2.0.2), this is not possible.
The pattern is applied to the filename only (the d_name member of the a struct dirent).
See here, the getinfo function gets called from here.
Related
I am trying to use make to build a set of markdown documents from specific and shared files.
PKGS := foo bar baz app
DEFAULT := DEPENDENCIES.md RULES.md
BUILD := .build
VPATH := .:packages
$(BUILD)/%.history.md: $(DEFAULT) $(wildcard %/RULES.*.md) $(foreach f,$(DEFAULT),%/$(f))
echo "!! BUILDING NOW $#"
echo $^
echo
with the following directory structure:
.
├── ABSTRACT.md
├── DEPENDENCIES.md
├── IMPLEMENTATION.md
├── Makefile
├── packages
│ ├── foo
│ │ ├── ABSTRACT.md
│ │ ├── DEPENDENCIES.md
│ │ ├── IMPLEMENTATION.md
│ │ ├── RULES.0.md -> ../COMMON.md
│ │ └── RULES.md
│ ├── COMMON.md
│ ├── bar
│ │ ├── ABSTRACT.md
│ │ ├── DEPENDENCIES.md
│ │ ├── IMPLEMENTATION.md
│ │ └── RULES.md
│ ├── baz
│ │ ├── ABSTRACT.md
│ │ ├── DEPENDENCIES.md
│ │ ├── IMPLEMENTATION.md
│ │ └── RULES.md
│ └── app
│ ├── ABSTRACT.md
│ ├── DEPENDENCIES.md
│ ├── IMPLEMENTATION.md
│ ├── RULES.0.md -> ../COMMON.md
│ └── RULES.md
└── RULES.md
However, $(wildcard %/RULES.*.md) always seems to expand into an empty list.
When executing make .build/foo.history.md I expected it to evaluate the prerequisites as DEPENDENCIES.md RULES.md packages/foo/RULES.0.md packages/foo/DEPENDENCIES.md packages/foo/RULES.md but instead I see this:
make .build/foo.history.md
echo "!! BUILDING NOW .build/foo.history.md"
!! BUILDING NOW .build/foo.history.md
echo DEPENDENCIES.md RULES.md packages/foo/DEPENDENCIES.md packages/foo/RULES.md
DEPENDENCIES.md RULES.md packages/foo/DEPENDENCIES.md packages/foo/RULES.md
echo
I've also tried adding some extra targets to better understand the process:
# Pattern rule with `%` as a directory clearly works.
%.static: %/RULES.0.md
echo $# -> $^
%.semi: %/RULES.*.md
echo $# -> $^
%.x: $(wildcard packages/%/RULES.*.md)
echo $# -> $^
# Wildcards using * also clear work.
app.y: $(wildcard packages/app/RULES.*.md)
echo $# -> $^
# Combination of both fails.
# I expect that if the target is `foo.z` for the prerequisites to expand into `foo/RULES.*.md`,
# searching within the VPATH.
%.z: $(wildcard %/RULES.*.md)
echo $# -> $^
Which results in this:
$ make app.static --just-print
echo app.static -> packages/app/RULES.0.md
$ make app.semi --just-print
make: *** No rule to make target 'app.semi'. Stop.
$ make app.x --just-print
echo app.x ->
$ make app.y --just-print
echo app.y -> packages/app/RULES.0.md
$ make app.z --just-print
echo app.z ->
I've also tried using .SECONDEXPANSION, but I couldn't get it to work with that either and I keep seeing other people recommending against it.
Additionally, it does work for $(foreach f,$(DEFAULT),%/$(f)) expanding correctly into packages/app/DEPENDENCIES.md packages/app/RULES.md which adds confusion as to why it doesn't work in $(wildcard).
The high-level problem is that you're trying to use too many unfamiliar tools at once. Let's take VPATH out of the picture for now.
The wildcard function will work, with secondary expansion:
.SECONDEXPANSION:
$(BUILD)/%.history.md: $$(wildcard packages/%/RULES.*.md)
echo "!! BUILDING NOW $#"
echo $^
echo
Notice that we must escape the $ in the prerequisite list with another $. I don't know why people advised against secondary expansion, but I see no easier way to get the effect you want.
Now about that VPATH. There isn't much need for it, since you want to search only one directory (packages/). Also, it doesn't work well with wildcard because VPATH tells Make where to look for prerequisites; it doesn't tell wildcard where to look for matches. And Make doesn't know what prerequisite to look for until after wildcard has done its work, which it can't because it doesn't know where to look. I advise you to do without it.
My folder structure is as follows:
there are 100 folders and every folder has 3 sub folders (imagine A, B and C). My task is to delete files which has specific text inside folder C only, from all the 100 folders.
i have minimal knowledge on Unix commands and my task is to perform on AIX server
i tried to google around and found the script below (it actually doesn't do the deletion).
and when i tried to execute the following script , i get the following error
"test.sh[5]: accepted: not found."
but there is actually "accepted" folder existed.not sure why the error is occurred.
for dir in $(ls)
do
for dir2 in $(ls)
do
cd accepted
echo $(ls)
done
done
Could any one help me update the script to perform "loop through sub folders inside a folder and delete files contains specific text inside specific sub folder only" ?
Let me assume the directory tree as an example:
X
├── A
│ ├── D
│ │ ├── bar.txt
│ │ └── foo.txt
│ ├── E
│ │ ├── bar.txt
│ │ └── foo.txt
│ └── F
│ ├── bar.txt
│ └── foo.txt
├── B
│ ├── D
│ │ ├── bar.txt
│ │ └── foo.txt
│ ├── E
│ │ ├── bar.txt
│ │ └── foo.txt
│ └── F
│ ├── bar.txt
│ └── foo.txt
└── C
├── D
│ ├── bar.txt
│ └── foo.txt
├── E
│ ├── bar.txt
│ └── foo.txt
└── F
├── bar.txt
└── foo.txt
And suppose you want to remove files which starts with foo from the directory F only.
Then please try the following:
find X/*/F -type f -name "foo*" -delete
Now the directory tree will look like:
X
├── A
│ ├── D
│ │ ├── bar.txt
│ │ └── foo.txt
│ ├── E
│ │ ├── bar.txt
│ │ └── foo.txt
│ └── F
│ └── bar.txt
├── B
│ ├── D
│ │ ├── bar.txt
│ │ └── foo.txt
│ ├── E
│ │ ├── bar.txt
│ │ └── foo.txt
│ └── F
│ └── bar.txt
└── C
├── D
│ ├── bar.txt
│ └── foo.txt
├── E
│ ├── bar.txt
│ └── foo.txt
└── F
└── bar.txt
I hope this meets your requirement.
While possible to implement the logic for identifying the files using tree search, this is not required for this case. Consider the following.
Note that solution will NOT work if any file names have special characters (spaces, quotes, new lines). It will work for "normal" file names (With the characters a-zA-Z0-9_-. etc)..
file_list=$(grep -l SomeText */C/*)
rm $file_list
Possible to combine into one line - use with care
rm $(grep -l SomeText */C/*)
You can also use rm -i instead of rm to get prompted for each file to be removed, if needed.
I have several folders for each year and inside of those folders there are files corresponding different stations. Somewhat like this:
.
├── 2017.1
│ ├── AAAA.2017
│ ├── BBBB.2017
│ └── CCCC.2017
├── 2018.1
│ ├── AAAA.2018
│ ├── BBBB.2018
│ └── CCCC.2018
└── 2019.1
├── AAAA.2019
├── BBBB.2019
└── CCCC.2019
What I want to do is to move all of these files into the main directory "."according to their name, so it would be something like this:
├── AAAA
│ ├── AAAA.2017
│ ├── AAAA.2018
│ └── AAAA.2019
├── BBBB
│ ├── BBBB.2017
│ ├── BBBB.2018
│ └── BBBB.2019
├── CCCC
│ ├── CCCC.2017
│ ├── CCCC.2018
│ └── CCCC.2019
I tried some simple code in which I create the folders and simply move the files according to their station. I was wondering if there was a more "elegant" or simple way of doing it
mkdir AAAA BBBB CCCC
for file in 20*/AAAA*; do
cp "$file" "/Users/admin/Desktop/test/AAAA"
done
for file in 20*/BBBB*; do
cp "$file" "/Users/admin/Desktop/test/BBBB"
done
for file in 20*/CCCC*; do
cp "$file" "/Users/admin/Desktop/test/CCCC"
done
I suggest while loop solution.
SRC_DIR=/path/to/dir
DEST_DIR=/tmp
cd "${SRC_DIR}"
find . -type f \
| while read -r FILE; do
BASENAME=${FILE##*/}
mkdir -p "${DEST_DIR}/${BASENAME%.*}" && cp -a $FILE "${DEST_DIR}/${BASENAME%.*}"
done
I have the following folder structure:
myfolder/
├── mysubfolder/
│ ├── x.txt
│ ├── y.txt
│ ├── z.txt
├── a.txt
├── b.txt
├── c.txt
├── d.txt
I'd like to copy only the top-level files (no subfolders) into a backup folder under the same folder, like so:
myfolder/
├── mysubfolder/
│ ├── x.txt
│ ├── y.txt
│ ├── z.txt
├── backup/
│ ├── a.txt
│ ├── b.txt
│ ├── c.txt
│ ├── d.txt
├── a.txt
├── b.txt
├── c.txt
├── d.txt
How can I achieve this with a copy task? I'm trying the following:
copy {
from "myfolder"
into "myfolder/backup"
include "*"
exclude "**"
}
But that doesn't seem to be working.
This worked:
copy {
from "myfolder"
into "myfolder/backup"
exclude {it.file.isDirectory()}
}
I'm using GNU Make on Arch Linux to generate PDFs from LilyPond source files. I have a directory structure as follows:
scores/
├── makefile
├── out
│ ├── others-songs
│ │ ├── ...
│ │ ├── ...
│ │ └── 失恋阵线联盟
│ │ ├── 失恋阵线联盟.edition.log
│ │ ├── 失恋阵线联盟.oll.log
│ │ └── 失恋阵线联盟.pdf
│ └── ...
├── src
│ ├── others-songs
│ │ ├── ...
│ │ ├── ...
│ │ └── 失恋阵线联盟
│ │ ├── chorus.ily
│ │ ├── verse.ily
│ │ ├── words.ily
│ │ └── 失恋阵线联盟.ly
│ └── ...
The PDFs in the out directory depend on the .ily and .ly files in the corresponding directory in src. The following implicit pattern rule works if the .ly file is modified, but not if any of the other files are:
LY = $(shell find src -iname '*.ly')
PDF = $(subst src,out,$(LY:.ly=.pdf))
pdf: $(PDF)
out/%.pdf: src/%.ly
#mkdir -p $(dir $#)
#lilypond --include=$(lib) \
-dpoint-and-click=\#f \
-o $(basename $#) $<
I tried doing several different things, like appending $(<D)*.ily to the prerequisites, but it wasn't successful. I've looked at the GNU make manual online for help, but I didn't come up with anything that that I was able to apply to my particular situation.
How can I write a pattern rule that makes each PDF depend on all the files in the appropriate corresponding source directory?
EDIT
I may not have been clear enough with my first question. The behavior I want is if any of the files in the source directories are changed, the corresponding PDF is updated. For example, if chorus.ily is changed, then 失恋阵线联盟.ly is made.
A working example:
LY := $(shell find src -iname '*.ly')
PDF := ${LY:src/%.ly=out/%.pdf}
pdf: $(PDF)
define pdf_deps
$(1:src/%.ly=out/%.pdf) : $(wildcard $(dir ${1})*)
endef
# Make each pdf depend on all the files in its src directory.
$(foreach ly,${LY},$(eval $(call pdf_deps,${ly})))
out/%.pdf:
#echo "making $# from $^"
Usage:
$ ls -1R
.:
Makefile
out
src
./out:
./src:
A
B
./src/A:
a.ly
./src/B:
b.1
b.ly
$ make
making out/B/b.pdf from src/B/b.ly src/B/b.1
mkdir -p out/B
touch out/B/b.pdf
making out/A/a.pdf from src/A/a.ly
mkdir -p out/A
touch out/A/a.pdf
$ make
make: Nothing to be done for 'pdf'.
$ touch src/B/b.ly
$ make
making out/B/b.pdf from src/B/b.ly src/B/b.1
mkdir -p out/B
touch out/B/b.pdf
$ make
make: Nothing to be done for 'pdf'.
$ touch src/B/b.1
$ make
making out/B/b.pdf from src/B/b.ly src/B/b.1
mkdir -p out/B
touch out/B/b.pdf
$ make
make: Nothing to be done for 'pdf'.