How do I display a tree of things in Bash? - bash

How do I make a tree of all things with bash? What is the command?

tree /
or
find /
Update: #OP, since you have so much trouble with it, how about this alternative. On ubuntu 9.10, you should have bash 4.0 ? so try this
#!/bin/bash
shopt -s globstar
for rdir in /*/
do
for file in $rdir/**
do
echo "$file"
done
done

you should probably alias this :)
ls -R | grep ":$" | sed -e 's/:$//' -e 's/[^-][^\/]*\//--/g' -e 's/^/ /' -e 's/-/|/'
(Warning: huge output)

$ find . -print | sed -e 's;/*/;|;g;s;|; |;g'
Add alias to ~/.bash_profile
alias tree="find . -print | sed -e 's;/*/;|;g;s;|; |;g'"

tree -R /
and then cry because it's enormous.
On a related note, to stop the command, press CTRL+C

Assuming you want to find something from tree, do
tree / > tree.txt
Then Ctrl + F it.

Related

Recursive grep-sed yields error: sed: -e expression #1, char 1: unknown command: `?' [duplicate]

I run this command to find and replace all occurrences of 'apple' with 'orange' in all files in root of my site:
find ./ -exec sed -i 's/apple/orange/g' {} \;
But it doesn't go through sub directories.
What is wrong with this command?
Here are some lines of output of find ./:
./index.php
./header.php
./fpd
./fpd/font
./fpd/font/desktop.ini
./fpd/font/courier.php
./fpd/font/symbol.php
Your find should look like that to avoid sending directory names to sed:
find ./ -type f -exec sed -i -e 's/apple/orange/g' {} \;
For larger s&r tasks it's better and faster to use grep and xargs, so, for example;
grep -rl 'apples' /dir_to_search_under | xargs sed -i 's/apples/oranges/g'
Since there are also macOS folks reading this one (as I did), the following code worked for me (on 10.14)
egrep -rl '<pattern>' <dir> | xargs -I# sed -i '' 's/<arg1>/<arg2>/g' #
All other answers using -i and -e do not work on macOS.
Source
This worked for me:
find ./ -type f -exec sed -i '' 's#NEEDLE#REPLACEMENT#' *.php {} \;
grep -e apple your_site_root/**/*.* -s -l | xargs sed -i "" "s|apple|orange|"
Found a great program for this called ruplacer
https://github.com/dmerejkowsky/ruplacer
Usage
ruplacer before_text after_text # prints out list of things it will replace
ruplacer before_text after_text --go # executes the replacements
It also respects .gitignore so it won't mess up your .git or node_modules directories (find . by default will go into your .git directory and can corrupt it!!!)
I think we can do this with one line simple command
for i in `grep -rl eth0 . 2> /dev/null`; do sed -i ‘s/eth0/eth1/’ $i; done
Refer to this page.
In linuxOS:
sed -i 's/textSerch/textReplace/g' namefile
if "sed" not work try :
perl -i -pe 's/textSerch/textReplace/g' namefile

how to substitute the beginning of file names in Mac OS X?

Under my folder, there are a lot of files all starting with "abcd", like "abcd****".
What I am going to do is change all the files names replacing "abcd" by "xyz".
How to use shell command like "find" "sed" to do this?
A simple method would be something like this:
for i in abcd*; do mv "$i" "xyz${i#abcd}"; done
Using a combination of ls, sed and xargs you could use:
ls * | sed -e 'p;s!^abcd!xyz!' | xargs -n2 mv
Result:
abcd.png → xyz.png
* to do a dry-run first, replace mv at the end with echo
for f in abcd*; do mv "$f" "$(echo "$f" | sed 's/^abcd/xyz/g')"; done

grep a pattern in list of zip files recursively

I am using the following command on command line for getting the pattern matched lines.
find . -name "*.gz"|xargs gzcat|grep -e "pattern1" -e "pattern2"
i need now to find only the file names where the pattern is present.
how can i do it on command line?
grel -l has no use since i am using xargs gzcat before grep
Check if you have zgrep available. And then, if yes:
find . -name '*.gz' -exec zgrep -l -e ".." -e ".." {} +
If you don't have it - well, just copy it from some machine that has it (all linuxes I use have it by default) - it's a simple bash script.
ripgrep
Use ripgrep, for example, it's very efficient, especially for large files:
rg -z -e "pattern1" -e "pattern2" *.gz
or:
rg -z "pattern1|pattern2" .
or:
rg -zf pattern.file .
Where pattern.file is a file containing all your patterns separated by a new line character.
-z/--search-zip Search in compressed files (such as gz, bz2, xz, and lzma).
for i in $(find . -name "*.gz"); do gzcat $i|grep -qe "n1" -e "n2" && echo $i; done
Untested; does everything inside find so if you have loads of gz files you wont have performance problems as runs each gzcat/grep as soon as it finds files nothing is piped out:
find . -iname '*.gz' -exec bash -c 'gzcat $1 | grep -q -e "pattern1" -e "pattern2" && echo $1' {} {} \;
In bash, I'd do something like this (untested):
find . -name '*.gz' | while read f ; do gzcat $f | grep -q -e "pattern1" -e "pattern2" && echo $f ; done
grep/zgrep/zegrep
Use zgrep or zegrep to look for pattern in compressed files using their uncompressed contents (both GNU/Linux and BSD/Unix).
On Unix, you can also use grep (which is BSD version) with -Z, including -z on macOS.
Few examples:
zgrep -E -r "pattern1|pattern2|pattern3" .
zegrep "pattern1|pattern2|pattern3" **/*.gz
grep -z -e "pattern1" -e "pattern2" *.gz # BSD/Unix only.
Note: When you've globbing option enabled, ** checks the files recursively, otherwise use -r.
-R/-r/--recursive Recursively search subdirectories listed.
-E/--extended-regexp Interpret pattern as an extended regular expression (like egrep).
-Z (BSD), -z/--decompress (BSD/macOS) Force grep to behave as zgrep.

xargs to execute a string - what am I doing wrong?

I'm trying to rename all files in current directory such that upper case name is converted to lower. I'm trying to do it like this:
ls -1|gawk '{print "`mv "$0" "tolower($0)"`"}'|xargs -i -t eval {}
I have two files in the directory, Y and YY
-t added for debugging, and output is:
eval `mv Y y`
xargs: eval: No such file or directory
if I execute the eval on its own, it works and moves Y to y.
I know there are other ways to achieve this, but I'd like to get this working if I can!
Cheers
eval is a shell builtin command, not a standalone executable. Thus, xargs cannot run it directly. You probably want:
ls -1 | gawk '{print "`mv "$0" "tolower($0)"`"}' | xargs -i -t sh -c "{}"
Although you're looking at an xargs solution, another method to perform the same thing can be done with tr (assuming sh/bash/ksh syntax):
for i in *; do mv $i `echo $i | tr '[A-Z]' '[a-z]'`; done
If your files are created by creative users, you will see files like:
My brother's 12" records
The solutions so far do not work on that kind of files. If you have GNU Parallel installed this will work (even on the files with creative names):
ls | parallel 'mv {} "$(echo {} | tr "[:upper:]" "[:lower:]")"'
Watch the intro video to learn more: http://www.youtube.com/watch?v=OpaiGYxkSuQ
You can use eval with xargs like the one below.
Note: I only tested this in bash shell
ls -1| gawk '{print "mv "$0" /tmp/"toupper($0)""}'| xargs -I {} sh -c "eval {}"
or
ls -1| gawk '{print "mv "$0" /tmp/"toupper($0)""}'| xargs -I random_var_name sh -c "eval random_var_name"
I generally use this approach when I want to avoid one-liner for loop.
e.g.
for file in $(find /some/path | grep "pattern");do somecmd $file; done
The same can be written like below
find /some/path | grep "pattern"| xargs -I {} sh -c "somecmd {}"

replace a particular text in all the files using single line shell command

I have a renamed js file which I have to call in each of my php pages. Now I want to replace that old name with the new one using shell.
what iam using is this:
sed -i ’s/old/new/g’ *
but this is giving the following error:
sed: -e expression #1, char 1: unknown command:
How can I do this replacement?
sed -i.bak 's/old/new/g' *.php
to do it recursively
find /path -type f -iname '*.php' -exec sed -i.bak 's/old/new/' "{}" +;
There are probably less verbose solutions, but here we go:
for i in *; do sed -i 's/old/new/g' "$i"; done
Mind you, it will only work on the current level of the file system, files in subdirectories will not be modified. Also, you might want to replace * with *.php, or make backups (pass an argument after -i, and it will make a backup with the given extension).
this one is very simple, without for or loop, and takes care of any number or nested directories
grep -rl 'oldText' [folderName-optional] | xargs sed -i 's/oldText/newText/g'
You are using Unicode apostrophes (RIGHT SINGLE QUOTATION MARK - U2019) instead of ASCII (0x27) apostrophes around your sed command argument.
I know I'm really late but still:
find . -type f -name "*.php"|xargs sed -i 's/old/new/g'
perl -pi -e 's/old/new/g' *.php
For completeness, providing the OSX compatible version of the above accepted answer (to answer comment from #jamescampbell)
for i in *.php; do sed -i .orig 's/old/new/g' "$i"; done
This command creates .orig backup files.
Try this:
ls | grep "php" > files.txt
for file in $(cat files.txt); do
sed 's/catch/send/g' $file > TMPfile.php && mv TMPfile.php $file
done

Resources