I was at a code interview which I failed, but I'm trying to understand it anyways.
From root, I was supposed to first get all html files and tar them on a single command.
After I failed, I was able to do it on my own like this:
find . -name "*.js" | xargs tar -cvf tar.tar
My problem is, it mimics the whole tree structure of the system. I wanted a solution that would put all the files on the same level, if I were to run on a folder with
-
| a.js
| b.html
| c.js
|_ folder
| g.html
My resulting tar ends up having a folder called folder with g.html in it. When ran from root, this looks terrible
root#i5-cpu:~/work_area/php# tree d1
d1
├── d2
│ ├── f2_1.js
│ └── f2_2.js
├── f1_1.js
└── f1_2.js
1 directory, 4 files
root#i5-cpu:~/work_area/php# find . -name "\*.js" | xargs tar -cvf tar.tar --transform='s,.*/,,'
./d1/d2/f2_1.js
./d1/d2/f2_2.js
./d1/f1_1.js
./d1/f1_2.js
root#i5-cpu:~/work_area/php# tar -tvf tar.tar
-rw-rw-rw- root/root 0 2019-01-17 01:12 f2_1.js
-rw-rw-rw- root/root 0 2019-01-17 01:12 f2_2.js
-rw-rw-rw- root/root 0 2019-01-17 01:11 f1_1.js
-rw-rw-rw- root/root 0 2019-01-17 01:11 f1_2.js
Check this page https://www.gnu.org/software/tar/manual/html_section/tar_51.html
The examples with --transform
Related
I am using the following command
zmv -n -Q '(**/)(*[[:upper:]]*)(/)' '${1}${(L)${2//(#b)([[:upper:]])/-$match[1]}#-}'
to transform
% tree
.
├── EmptyFile.txt
├── FirstDirectoryName
│ ├── FourthDirectoryName
│ ├── secondDirectoryName
│ └── thirdDirectoryName
├── FourthDirectoryName
├── secondDirectoryName
└── thirdDirectoryName
To
% tree
.
├── EmptyFile.txt
├── first-directory-name
│ ├── fourth-directory-name
│ ├── second-directory-name
│ └── third-directory-name
├── fourth-directory-name
├── second-directory-name
└── third-directory-name
However there is a small problem.
I do not want to lowercase if there are more than one consecutive uppercase letters. I just want to put - behind the capital letters given it is not in the beginning.
% tree
.
├── DDDDDDD
├── FirstFolderToRename
│ ├── DDDDDDD
│ └── ThisIsDDDDD
├── secondFolderToRename
│ ├── DDDDDDD
│ └── ThisIsDDDDD
└── ThisIsDDDDD
Current Output
% zmv -n -Q '(**/)(*[[:upper:]]*)(/)' '${1}${(L)${2//(#b)([[:upper:]])/-$match[1]}#-}'
mv -- FirstFolderToRename/DDDDDDD FirstFolderToRename/d-d-d-d-d-d-d
mv -- FirstFolderToRename/ThisIsDDDDD FirstFolderToRename/this-is-d-d-d-d-d
mv -- secondFolderToRename/DDDDDDD secondFolderToRename/d-d-d-d-d-d-d
mv -- secondFolderToRename/ThisIsDDDDD secondFolderToRename/this-is-d-d-d-d-d
mv -- DDDDDDD d-d-d-d-d-d-d
mv -- FirstFolderToRename first-folder-to-rename
mv -- secondFolderToRename second-folder-to-rename
mv -- ThisIsDDDDD this-is-d-d-d-d-d
Expected Output
mv -- FirstFolderToRename/DDDDDDD FirstFolderToRename/DDDDDDD
mv -- FirstFolderToRename/ThisIsDDDDD FirstFolderToRename/this-is-DDDDD
mv -- secondFolderToRename/DDDDDDD secondFolderToRename/DDDDDDD
mv -- secondFolderToRename/ThisIsDDDDD secondFolderToRename/this-is-DDDDD
mv -- DDDDDDD DDDDDDD
mv -- FirstFolderToRename first-folder-to-rename
mv -- secondFolderToRename second-folder-to-rename
mv -- ThisIsDDDDD this-is-DDDDD
Specify one or more upper case characters. That is [[:upper:]]## with zsh's extended globbing (which zmv uses). ## is similar to regex + quantifier. A single # is zero or more, similar to regex *.
zmv -n -Q '(**/)(*[[:upper:]]*)(/)' '${1}${(L)${2//(#b)([[:upper:]]##)/-$match[1]}#-}'
Optionally, convert leading upper case characters separately instead of removing initial - afterwards:
${1}${(LM)2##[[:upper:]]#}${(L)${2##[[:upper:]]#}//(#b)([[:upper:]]##)/-$match[1]}
From linuxquestions
function CamelOrPascalToKebab() {
zmv -Q '(**/)(*[A-Z]*)(/)' '$1${2//(#b)([a-z])([A-Z])/$match[1]-$match[2]}'
zmv -Q '(**/)(*[A-Z][a-z]*)(/)' '$1${2//(#m)[A-Z][a-z]/${(L)MATCH}}'
}
I have these JSON files in a large directory structure. Some are just "abc.json" and some the added ".finished". I want to rsync only the files without ".finished".
$ find
.
./a
./a/abc.json.finished
./a/abc.json <-- this file
./a/index.html
./a/somefile.css
./b
./b/abc.json.finished
./b/abc.json <-- this file
Sample rsync command that copies all the "abc.json" AND the "abc.json.finished". I just want the "abc.json".
$ rsync --exclude="finished" --include="*c.json" --recursive \
--verbose --dry-run . server:/tmp/rsync
sending incremental file list
created directory /tmp/rsync
./
a/
a/abc.json
a/abc.json.finished
a/index.html
a/somefile.css
b/
b/abc.json
b/abc.json.finished
sent 212 bytes received 72 bytes 113.60 bytes/sec
total size is 0 speedup is 0.00 (DRY RUN)
Update: Added more files to the folders. HTML files, CSS and other files are present in my scenario. Only files ending in "c.json" should be transferred.
Scenario can be recreated with the following commands:
mkdir a
touch a/abc.json.finished
touch a/abc.json
touch a/index.html
touch a/somefile.css
mkdir b
touch b/abc.json.finished
touch b/abc.json
Try the following command. It assumes that you also want to replicate the source directory tree, (for any directories containing files which end with c.json), in the destination location:
$ rsync --include="*c.json" --exclude="*.*" --recursive \
--verbose --dry-run . server:/tmp/rsync
Explanation of command:
--include="*c.json" includes only assets whose name ends with c.json
--exclude="*.*" excludes all other assets (i.e. assets whose name includes a dot .)
--recursive recurse into directories.
--verbose log the results to the console.
--dry-run shows what would have been copied, without actually copying the files. This option/flag should be omitted to actually perform the copy task.
. the path to the source directory.
server:/tmp/rsync the path to the destination directory.
EDIT: Unfortunately, the command provided above also copies files whose filename does not include a dot character. To avoid this consider utlizing both rsync and find as follows:
$ rsync --dry-run --verbose --files-from=<(find ./ -name "*c.json") \
./ server:/tmp/rsync
This utilizes process substitution, i.e. <(list), to pass the output from the find command to the --files-from= option/flag of the rsync command.
source tree
.
├── a
│ ├── abc.json
│ ├── abc.json.finished.json
│ ├── index.html
│ └── somefile.css
└── b
├── abc.json
└── abc.json.finished.json
resultant destination tree
server
└── tmp
└── rsync
├── a
│ └── abc.json
└── b
└── abc.json
A hacky solution is use grep and create a file containing all file names we want to transfer.
find |grep "c.json$" > rsync-files
rsync --files-from=rsync-files --verbose --recursive --compress --dry-run \
./ \
server:/tmp/rsync
rm rsync-files
Content of 'rsync-files':
./a/abc.json
./b/abc.json
Output when running rsync command:
sending incremental file list
created directory /tmp/rsync
./
a/
a/abc.json
b/
b/abc.json
I'm quite new to makefile but I still cannot understand how to set up the subdirectories of my source files.
My directory tree is:
i18n/
src/
engine/
graphics/ (currently only directory used)
I'm using this premade Makefile:
TARGET = caventure
LIBS = -lSDL2
CC = g++
CFLAGS = -Wall
TGTDIR = build
.PHONY: default all clean
default: $(TARGET)
all: default
OBJECTS = $(patsubst %.cpp, %.o, $(wildcard *.cpp))
HEADERS = $(wildcard *.h)
%.o: %.cpp $(HEADERS)
$(CC) $(CFLAGS) -c $< -o $#
.PRECIOUS: $(TARGET) $(OBJECTS)
$(TARGET): $(OBJECTS)
$(CC) $(OBJECTS) -Wall $(LIBS) -o $(TGTDIR)/$(TARGET)
clean:
-rm -f *.o
-rm -f $(TARGET)
GNU make's wildcard function does not recursively visit all subdirectories.
You need a recursive variant of it, which can be implemented as described in this answer:
https://stackoverflow.com/a/18258352/1221106
So, instead of $(wildcard *.cpp) you need to use that recursive wildcard function.
Another simpler way of finding files recursively might be to just use find.
For example, if you have a layout like this.
$ tree .
.
├── d1
│ └── foo.txt
├── d2
│ ├── d4
│ │ └── foo.txt
│ └── foo.txt
├── d3
│ └── foo.txt
└── Makefile
You could write a Makefile like this.
index.txt: $(shell find . -name "*.txt")
echo $^
Which prints this.
$ make
echo d2/d4/foo.txt d2/foo.txt d1/foo.txt d3/foo.txt
d2/d4/foo.txt d2/foo.txt d1/foo.txt d3/foo.txt
I want to restore previous backuped directory (spect folder into /opt)
Architecture (Solaris 10) :
root#sms01sxdg /opt> ls -ltr
total 22
[...]
drwxr-xr-x 2 specadm nms 1024 Dec 24 13:40 spect
root#sms01sxdg /opt>
root#sms01sxdg /opt> df -kh
Filesystem size used avail capacity Mounted on
/dev/md/dsk/d0 9.8G 4.2G 5.6G 43% /
[...]
/dev/md/dsk/d30 7.9G 94M 7.7G 2% /opt/spect
root#sms01sxdg /opt>
I have previously backuped folder with tar command : tar cvf spect.tar spect.
It has worked successfully and when I launch tar -tf spect.tar it shows the sub-folders/files into.
When I try to restore backup, it doesn't work or more precisely, it returns nothing and files are finally not extracted.
root#sms01sxdg /opt> tar -xvf /export/specbackup_db/spect.tar .
root#sms01sxdg /opt> ls -l spect/
total 0
root#sms01sxdg /opt>
I suspect that the folder I have backup is a mount point and it is the cause of this problem.
But it seems the mount point is still mounted.
I have always performed this kind of command but it is the first time I encounter this kind.
Try again after removing the dot at the end of the command. Generally, you can specify the files that should be extracted from the tar by listing their paths after the tar file name ex: tar -xvf tarfile.tar file1 file2. this will extract only file1 and file2 from the tarfile.tar.
I have access to unix server from Putty application. Can anyone tell me how can I view/print all the files and directories inside a directory.
I tried below by searching internet and not working. Not sure what actually they do!
find ./ -type d | awk -F "/" '{ ld=0x2500; lt=0x251c; ll=0x2502; for (i=1; i<=NF-2; i++){printf "%c ",ll} printf "%c%c %s\n",lt,ld,$NF }'
and this
ls -R | grep ":$" | sed -e 's/:$//' -e 's/[^-][^\/]*\//--/g' -e 's/^/ /' -e 's/-/|/'
The tool tree will help you, while at it, you might also want to install pstree.
19:38:05 dusted#mono~
$ tree test
test
├── a
│ ├── 1
│ ├── 2
│ └── 3
├── b
│ ├── 1
│ ├── b
│ └── c
├── b-files.txt
├── new-b-files.txt
├── newer-b-files.txt
└── test
2 directories, 10 files
Hey there I did a little searching and stumbled upon a site that explains what you are asking. Let us know if this leads you in the right direction...http://www.centerkey.com/tree/
The 'find' command should do the job:
find /path/to/directory
If you want more information for each entry, you can combine 'find' with 'ls' like this:
find /path/to/directory -exec ls -ld "{}" \;