Octal

Shell tricks

84 posts in this topic

OK here's a real trick.

How to read directories with spaces in them (eg. /home/tehbizz/my mp3s) into an array or anything else. I had to do this for a script I was working on for some recursive copying (NOT cp -r, that's for copying entire directories from A to B, not copying file A to directories A-Z). This is how I had to do it:

`set IFS=$'\n'`

This sets $IFS (internal field separator) to simply \n or newlines. Normally IFS is set to space horizontal tab newline (in that order) so whenever a space is encountered, IFS breaks and proceeds to the next item. As you can imagine, this is quite a problem when you are encountered folders with spaces in them and setting $IFS to only break on newlines fixes it immediately. Actually finding this solution took a good 8 or so days of trial and error and a ton of reading since not a lot of people ever bother with changing $IFS because its typical state of " \t\n" works for just about everything in the first place.

0

Share this post


Link to post
Share on other sites

tehbiz, I have always used this:

cd /home/tehbizz/my\ mp3s

The '\ ' identifys a space in the file, just so bash won't think it is another day.

This took a good 5 seconds, and found out with a hit of tab because I am too lazy to type out a full name.

0

Share this post


Link to post
Share on other sites
tehbiz, I have always used this:

cd /home/tehbizz/my\ mp3s

The '\ ' identifys a space in the file, just so bash won't think it is another day.

This took a good 5 seconds, and found out with a hit of tab because I am too lazy to type out a full name.

I know that a \ will escape a space, putting quotes around it will do the same. Single quotes can serve the same purpose. You can even use sed or cut to chop out the spaces. However, I know this and this was /not/ what I was looking to do. Re-read my post and you'll realize that this would never work in an array as $IFS would break immediately on your space.

Try making a few directory names with spaces in them and then try to read each one into an array, you won't get the result that you expect without changing $IFS. In fact, here's a script to do it for you and echo the results:

#!/bin/bash -

mkdir "test 1"
mkdir "test 2"
mkdir "test 3"
mkdir "test 4"

for dir in $(ls $PWD)
do
echo $dir
done

exit 0

Now, see if it echoes this:

test 1
test 2
test 3
test 4

And you'll realize what my trick is exactly talking about.

0

Share this post


Link to post
Share on other sites
OK here's a real trick.

How to read directories with spaces in them (eg. /home/tehbizz/my mp3s) into an array or anything else. I had to do this for a script I was working on for some recursive copying (NOT cp -r, that's for copying entire directories from A to B, not copying file A to directories A-Z). This is how I had to do it:

`set IFS=$'\n'`

This sets $IFS (internal field separator) to simply \n or newlines. Normally IFS is set to space horizontal tab newline (in that order) so whenever a space is encountered, IFS breaks and proceeds to the next item. As you can imagine, this is quite a problem when you are encountered folders with spaces in them and setting $IFS to only break on newlines fixes it immediately. Actually finding this solution took a good 8 or so days of trial and error and a ton of reading since not a lot of people ever bother with changing $IFS because its typical state of " \t\n" works for just about everything in the first place.

I understand what you mean and it is a great solution.

0

Share this post


Link to post
Share on other sites
OK here's a real trick.

How to read directories with spaces in them (eg. /home/tehbizz/my mp3s) into an array or anything else. I had to do this for a script I was working on for some recursive copying (NOT cp -r, that's for copying entire directories from A to B, not copying file A to directories A-Z). This is how I had to do it:

`set IFS=$'\n'`

This sets $IFS (internal field separator) to simply \n or newlines. Normally IFS is set to space horizontal tab newline (in that order) so whenever a space is encountered, IFS breaks and proceeds to the next item. As you can imagine, this is quite a problem when you are encountered folders with spaces in them and setting $IFS to only break on newlines fixes it immediately. Actually finding this solution took a good 8 or so days of trial and error and a ton of reading since not a lot of people ever bother with changing $IFS because its typical state of " \t\n" works for just about everything in the first place.

Rock on.. From bitching (no offense) to leading the way.. :)

You've just made the thread more interesting...

0

Share this post


Link to post
Share on other sites

How about another one...

If you are desperate to find a file but you only know a word or two then you can use this to dig really deep into your hard drive. FYI: This could talke a fairly long time on a large drive but if you gotta you gotta.

find * -exec strings -a -f -n 11 {} \; | grep "death eater"

Notice that the number 11 matches the number of letters and spaces in the word "deatheater". Make sure you change the number to match your search term.

Edited by nullkraft
0

Share this post


Link to post
Share on other sites

This hasn't been mentioned yet:

A wildcard: *

You could put it like this:

ls *.c

would show all files in that directory that end with '.c' you could also use it like this:

ls hello*.c

would display all files in that directory that end with .'c' and start with 'hello'.

That can be helpful when you are dealing with many files in one directory.

0

Share this post


Link to post
Share on other sites

GNU bash, version 3.1.17(1)-release (i686-pc-linux-gnu):

poop@speedy ~ $ ls -laSh

total 4.5K

-rw-r--r-- 1 poop poop 1.1K Aug 26 07:16 .bashrc

-rw-r--r-- 1 poop poop 193 Aug 26 07:16 .bash_profile

-rw------- 1 poop poop 159 Jan 29 13:38 .bash_history

-rw-r--r-- 1 poop poop 127 Aug 26 07:16 .bash_logout

drwxr-xr-x 3 poop poop 7 Feb 2 13:29 .

drwxr-xr-x 3 root root 4 Aug 26 07:16 ..

drwx------ 2 poop poop 3 Dec 18 20:13 .irssi

poop@speedy ~ $ echo "i hate typing things twice" >> afile

poop@speedy ~ $ !e

echo "i hate typing things twice" >> afile

poop@speedy ~ $ cat afile

i hate typing things twice

i hate typing things twice

poop@speedy ~ $ history | tail -n 3

38 echo "i hate typing things twice" >> afile

39 cat afile

40 history | tail -n 3

poop@speedy ~ $!38

echo "i hate typing things twice" >> afile

poop@speedy ~ $ cat afile

i hate typing things twice

i hate typing things twice

i hate typing things twice

poop@speedy ~ $

0

Share this post


Link to post
Share on other sites
This hasn't been mentioned yet:

A wildcard: *

You could put it like this:

ls *.c

would show all files in that directory that end with '.c' you could also use it like this:

ls hello*.c

would display all files in that directory that end with .'c' and start with 'hello'.

That can be helpful when you are dealing with many files in one directory.

Still not a trick. This is explained in the manpage.

0

Share this post


Link to post
Share on other sites
Still not a trick. This is explained in the manpage.

I thought the idea was just to post shortcuts we use on a daily bases to make our lives easier when working with shells (be it explained in a manual page or not).

Your "trick" is explained in a man page as well: try looking in SH(1)

0

Share this post


Link to post
Share on other sites
Still not a trick. This is explained in the manpage.

I thought the idea was just to post shortcuts we use on a daily bases to make our lives easier when working with shells (be it explained in a manual page or not).

Your "trick" is explained in a man page as well: try looking in SH(1)

Actually what I posted is not what IFS is but how to fully read spaced items correctly. Here's what man 1 sh has to say:

IFS The Internal Field Separator that is used for word splitting after expansion and to split lines into words with the read builtin command. The default value is ‘‘<space><tab><newline>’’

Now, it does go on to explain that:

Any element of an array may be referenced using ${name[subscript]}. The braces are required to avoid conflicts with pathname expansion. If subscript is @ or *, the word expands to all members of

name. These subscripts differ only when the word appears within double quotes. If the word is double-quoted, ${name[*]} expands to a single word with the value of each array member separated by the

first character of the IFS special variable, and ${name[@]} expands each element of name to a separate word.

Then this:

If the value of IFS is null, no word splitting occurs.

However, I didn't set it to null, I set it to newlines only. I tried null and it worked but not how I wanted it to, it globbed all array elements into a single element. And since IFS is supposed to honor shell quoting, I found this too to not work so only setting it to newlines was possible for exactly what I needed. Not only did I pour over my book on shell scripting and the Advanced Shell Scripting Guide, I read tens of posts on the web about how to do this and not one had the correct answer. Then not only did I actually consult people who've used UNIX longer than Linux has been around, I could never get a straight answer on exactly what to do because so few people ever think about what IFS is and what it does. It's surprising how many people don't even know it exists. Most references ever made to IFS are buried in text or appendices simply because it's a forgotten element of the shell.

Using * as a delimiter in a search is the village secret everyone knows about but how to use IFS is something so few know. That's what makes it a real trick. So far, a number of the posts in this thread are merely shortcuts, not actual tricks. Perhaps "shell shortcuts" would have been a more appropriate title.

0

Share this post


Link to post
Share on other sites

The OP makes clear the exact purpose of this thread:

I made this thread as a basic resource for people, like newbie hq. But this is based on intresting/time saving/etc ways to use a shell in unix.

never is "novel" brought up

thanks to everyone who is contributing though, keep the ``tricks" coming

0

Share this post


Link to post
Share on other sites
This hasn't been mentioned yet:

A wildcard: *

You could put it like this:

ls *.c

would show all files in that directory that end with '.c' you could also use it like this:

ls hello*.c

would display all files in that directory that end with .'c' and start with 'hello'.

That can be helpful when you are dealing with many files in one directory.

Along with *, which allows any number of characters, ? is the single character wildcard. Perfect when you have a folder with files named Pic1.jpg to Pic100.jpg but only want to change Pic20-29.jpg. So instead of Pic*.jpg which will affect all 100, use Pic2?.jpg

0

Share this post


Link to post
Share on other sites
This hasn't been mentioned yet:

A wildcard: *

You could put it like this:

ls *.c

would show all files in that directory that end with '.c' you could also use it like this:

ls hello*.c

would display all files in that directory that end with .'c' and start with 'hello'.

That can be helpful when you are dealing with many files in one directory.

Still not a trick. This is explained in the manpage.

If it was only 'tricks', there would only be you posting. Because obviously you decide what is a trick and what isn't. :P

0

Share this post


Link to post
Share on other sites

i use ctrl-r most i think: ctrl-r then start typing, it automatically greps your bash history. it's not much of a trick though :(

you can do this to use term as a calculator

echo 2+2|bc

you just have to remember the 'echo' and '|bc' bits

i've got a script i use called whatsmyip. it tells me my ip address lol it uses lynx. i've got another that's a proper calculator. i got them both from this link -

http://www.bashscripts.org/downloads/Scripts/crouse/

it's the script called calc.sh, not bashcalc.sh.

calchr0.th.png

0

Share this post


Link to post
Share on other sites

i've got this command as an alias i made :D

watch --interval=2 "sudo netstat -apn -l -A inet"

this is the alias

alias net1='watch --interval=2 "sudo netstat -apn -l -A inet"'

someone said they don't like aliases, but i think that one is important to be able to run quickly if you want to see what's happening on the network. it refreshes every 2 seconds 8)

Edited by iceni
0

Share this post


Link to post
Share on other sites

Ever accidentally cat'd a binary file to your terminal and ended up with a bunch of junk characters filling your screen and making the terminal useless? Try using the reset command to restore the correct character set.

0

Share this post


Link to post
Share on other sites

That sudo one is semi-dangerous, about as dangerous as leaving a root terminal up on your screen. Anyone can walk up, ^C out of it, and have passwordless sudo since you've been preventing it from timing out by re-launching the command every 2 minutes. Of course, sudo being the leet tool that it is gives you plenty of config options to get around that.

0

Share this post


Link to post
Share on other sites
Ugh, I don't want to talk about all the times I've seen some jackass dev get in a hurry, and chmod -R 777 an entire /var/www directory... All it takes is one time doing that, and the security of your system can be seriously compromised.

Have you been watching me?

0

Share this post


Link to post
Share on other sites

Hello everyone, thanks for the good information here!

I'm not really sure if you would want to consider this a "trick" or not but it's gotten me out of some sticky situations when sshing from one machine with my shell set as bash to another machine with my shell set as certain versions of ksh.

Basically if you find yourself in a situation where the backspace key is no longer working, and you don't feel like pressing ctrl-h to erase things all day, you can use "stty" to remap the erase key to the backspace button.

$ stty erase <press the key you wish you map erase to, usually backspace>

You can use stty to remap various other things as well (man stty =)

---

Oh yeah, another thing that may come in handy. (again sorry this may not be considered a trick)

On linux the 'killall' command will let you kill all of the processes with a given name. On some Solaris machines killall will flat out kill all processes... including init. :blowfuse:

A handy string of commands to use when you have a bunch of stray processes out there but you can't use killall is the following:

$ ps -aef | grep <process name> | awk '{print $2}' | xargs kill -9

Again not a trick, but a common, helpful, string that people may end up using :)

0

Share this post


Link to post
Share on other sites

Thanks for the leet :> trick. Btw, echo > file != :> file. echo leaves a newline in the file where :> leaves nothing. Prove it with od...

luser@windows:~$ echo >| test.txt
luser@windows:~$ od -h test.txt
0000000 0a00
0000001
luser@windows:~$ :>| test.txt
luser@windows:~$ od -h test.txt
luser@windows:~$

If you "set -o noclobber" then you have to use >| file.

0

Share this post


Link to post
Share on other sites

Try echo -n >file instead. No newline.

0

Share this post


Link to post
Share on other sites

wget -q -O 1.html "http://rds.yahoo.com/S=96062857/K=$1+$2/v=2/SID=e/TID=I047_86/l=IPGN/R=1/SIG=1451curee/EXP=1126931656/*-http%3A//images.search.yahoo.com/search/images?p=$1+$2&sm=Yahoo%21+Search&toggle=1&ei=UTF-8&&vm=p&prev_sBL=off&safesearch=1&imgsz=large&b=41"
grep 'fullsize' 1.html | sed 's/.*imgurl=/<img src="http:\/\//g' | sed -e 's/pg&rurl.*/pg">/g' | sed -e "s/%2F/\//g" | sed -e "s/%2520/_/g" | sed -e "s/%7E/~/g" | sed -e "s/%27/'/g" | sed -e "s/%40/@/g" >> $1-$2.html

http://rmccurdy.com/scripts/

0

Share this post


Link to post
Share on other sites

Look at this:

<user@dv5000t ~/> wtf
usage: wtf [-f dbfile] [-t type] [is] <acronym>
<user@dv5000t ~/$ wtf lol
LOL: laughing out loud
<user@dv5000t ~/>$ wtf rofl
ROFL: rolling on floor laughing

haha, that's a sweet command.

Edited by Octal
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now