How to list contents of another directory without being in it? - unix

Here is what my directory looks like:
Test ----
|
|----One
|
|----Two
I am attempting to list the contents of Two while still being in One and I am not able to do so.
I have tried this command (as seen in a other post) : "ls Test/" and it says No such file or directory. I have also tried ls Test/Two/ and it still does not work.

If you are in One and you want to list the contents of Two, you should go up to the parent directory using ..:
ls ../Two
../ will place you in the Test directory, from there, you can go to Two with no problem. If you have more depth levels, just add more ../ to go up one directory each time, but mind which is your current directory when running the command.

what does this command provide you in terminal.
ls -al Test //a flag is used for hidden file

Related

Moving files from current directory to one directory below

I am trying to move 2 files from current directory (/base/level1/level2) to one directory below (/base/level1)
Is there any easier command other than mv file1 /base/level1 ? I'm trying to understand if we have some command that move it to a specific level up or down in the current folder structure.
TIA!
My solution to this one is navigating to the path where I want to move the file and run the following command.
cp ./level2/file1 .
or
cp ./file1 ./level2/file1
Please share other solutions as well
Thanks,
AMK
You could use wildcards if the 2 files have something uniquely in common.
ie. mv file*.ext path/to/new/dest/
This will move all files starting with "file" and ending with the extension ".ext" to the destination. Have a look at this and this which will explain wildcards a bit more
You can always use .. for "one directory up".
And you can give more than 2 arguments to mv, the last always being the destination.
So mv file1 file2 .. would move those 2 files a directory up.
Or mv * .. to move all files.

Makefile rule depend on directory content changes

Using Make is there a nice way to depend on a directories contents.
Essentially I have some generated code which the application code depends on. The generated code only needs to change if the contents of a directory changes, not necessarily if the files within change their content. So if a file is removed or added or renamed I need the rule to run.
My first thought is generate a text file listing of the directory and diff that with the last listing. A change means rerun the build. I think I will have to pass off the generate and diff part to a bash script.
I am hoping somehow in their infinite intelligence might have an easier solution.
Kudos to gjulianm who got me on the right track. His solution works perfect for a single directory.
To get it working recursively I did the following.
ASSET_DIRS = $(shell find ../../assets/ -type d)
ASSET_FILES = $(shell find ../../assets/ -type f -name '*')
codegen: ../../assets/ $(ASSET_DIRS) $(ASSET_FILES)
generate-my-code
It appears now any changes to the directory or files (add, delete, rename, modify) will cause this rule to run. There is likely some issue with file names here (spaces might cause issues).
Let's say your directory is called dir, then this makefile will do what you want:
FILES = $(wildcard dir/*)
codegen: dir # Add $(FILES) here if you want the rule to run on file changes too.
generate-my-code
As the comment says, you can also add the FILES variable if you want the code to depend on file contents too.
A disadvantage of having the rule depend on a directory is that any change to that directory will cause the rule to be out-of-date — including creating generated files in that directory. So unless you segregate source and target files into different directories, the rule will trigger on every make.
Here is an alternative approach that allows you to specify a subset of files for which additions, deletions, and changes are relevant. Suppose for example that only *.foo files are relevant.
# replace indentation with tabs if copy-pasting
.PHONY: codegen
codegen:
find . -name '*.foo' |sort >.filelist.new
diff .filelist.current .filelist.new || cp -f .filelist.new .filelist.current
rm -f .filelist.new
$(MAKE) generate
generate: .filelist.current $(shell cat .filelist.current)
generate-my-code
.PHONY: clean
clean:
rm -f .filelist.*
The second line in the codegen rule ensures that .filelist.current is only modified when the list of relevant files changes, avoiding false-positive triggering of the generate rule.

How to use mv command to rename multiple files in unix?

I am trying to rename multiple files with extension xyz[n] to extension xyz
example :
mv *.xyz[1] to *.xyz
but the error is coming as - " *.xyz No such file or directory"
Don't know if mv can directly work using * but this would work
find ./ -name "*.xyz\[*\]" | while read line
do
mv "$line" ${line%.*}.xyz
done
Let's say we have some files as shown below.Now i want remove the part -(ab...) from those files.
> ls -1 foo*
foo-bar-(ab-4529111094).txt
foo-bar-foo-bar-(ab-189534).txt
foo-bar-foo-bar-bar-(ab-24937932201).txt
So the expected file names would be :
> ls -1 foo*
foo-bar-foo-bar-bar.txt
foo-bar-foo-bar.txt
foo-bar.txt
>
Below is a simple way to do it.
> ls -1 | nawk '/foo-bar-/{old=$0;gsub(/-\(.*\)/,"",$0);system("mv \""old"\" "$0)}'
for detailed explanation check here
Here is another way using the automated tools of StringSolver. Let us say your first file is named abc.xyz[1] a second named def.xyz[1] and a third named ghi.jpg (not the same extension as the previous two).
First, filter the files you want by giving examples (ok and notok are any words such that the first describes the accepted files):
filter abc.xyz[1] ok def.xyz[1] ok ghi.jpg notok
Then perform the move with the filter it created:
mv abc.xyz[1] abc.xyz
mv --filter --all
The second line generalizes the first transformation on all files ending with .xyz[1].
The last two lines can also be abbreviated in just one, which performs the moves and immediately generalizes it:
mv --filter --all abc.xyz[1] abc.xyz
DISCLAIMER: I am a co-author of this work for academic purposes. Other examples are available on youtube.
I think mv can't operate on multiple files directly without loop.
Use rename command instead. it uses regular expressions but easy to use once mastered and more powerful.
rename 's/^text-to-replace/new-text-you-want/' text-to-replace*
e.g to rename all .jar files in a directory to .jar_bak
rename 's/^jar/jar_bak/' jar*

Change to xth directory terminal

Is there a way in a unix shell (specifically Ubuntu) to change directory into the xth directory that was printed from the ls command?
I know you can sort a directory in multiple ways, but using the output from ls to get the xth directory?
An example shell:
$ ls
$ first_dir second_dir third_really_long_and_complex_dir
where I want to move into the third_really_long_and_complex_dir by passing 3 (or 2 in proper array format).
I know I could simply copy and paste, but if I'm already using the keyboard, it would be easier to type something like "cdls 2" or something like that if I knew the index.
The main problem with cd in an interactive session is that you generally want to change the current directory of the shell that is processing the command prompt. That means that launching a sub-shell (e.g. a script) would not help, since any cd calls would not affect the parent shell.
Depending on which shell you are using, however, you might be able to define a function to do this. For example in bash:
function cdls() {
# Save the current state of the nullglob option
SHOPT=`shopt -p nullglob`
# Make sure that */ expands to nothing when no directories are present
shopt -s nullglob
# Get a list of directories
DIRS=(*/)
# Restore the nullblob option state
$SHOPT
# cd using a zero-based index
cd "${DIRS[$1]}"
}
Note that in this example I absolutely refuse to parse the output of ls, for a number of reasons. Instead I let the shell itself retrieve a list of directories (or links to directories)...
That said, I suspect that using this function (or anything to this effect) is a very good way to set yourself up for an enormous mess - like using rm after changing to the wrong directory. File-name auto-completion is dangerous enough already, without forcing yourself to count...

Can I symlink multiple directories into one?

I have a feeling that I already know the answer to this one, but I thought I'd check.
I have a number of different folders:
images_a/
images_b/
images_c/
Can I create some sort of symlink such that this new directory has the contents of all those directories? That is this new "images_all" would contain all the files in images_a, images_b and images_c?
No. You would have to symbolically link all the individual files.
What you could do is to create a job to run periodically which basically removed all of the existing symbolic links in images_all, then re-create the links for all files from the three other directories, but it's a bit of a kludge, something like this:
rm -f images_all/*
for i in images_[abc]/* ; do; ln -s $i images_all/$(basename $i) ; done
Note that, while this job is running, it may appear to other processes that the files have temporarily disappeared.
You will also need to watch out for the case where a single file name exists in two or more of the directories.
Having come back to this question after a while, it also occurs to me that you can minimise the time during which the files are not available.
If you link them to a different directory then do relatively fast mv operations that would minimise the time. Something like:
mkdir images_new
for i in images_[abc]/* ; do
ln -s $i images_new/$(basename $i)
done
# These next two commands are the minimal-time switchover.
mv images_all images_old
mv images_new images_all
rm -rf images_old
I haven't tested that so anyone implementing it will have to confirm the suitability or otherwise.
You could try a unioning file system like unionfs!
http://www.filesystems.org/project-unionfs.html
http://aufs.sourceforge.net/
to add on to paxdiablo 's great answer, i think you could use cp -s
(-s or --symbolic-link)
which makes symbolic links instead of literal copying
to maybe speed up or simplify the the bulk adding of symlinks to the "merge" folder A , of the files from folder B and C.
(i have not tested this though)
I cant recall of the top of my head, but im sure there is some option for CP to NOT overwrite existing, thus only symlinks of new files will be "cp -s" ed

Resources