Subversion commands

Native commands

  • Revert current local folder to revision 666:
    svn merge -rHEAD:666 ./
    
  • Create an empty repository:
    svnadmin create ./my-repo
    
  • Dump a repository (a sure way to migrate a subversion repository from one version to another):
    svnadmin dump ./my-repo > ./my-repo.dmp
    
  • Migrate a remote Subversion repository without creating an intermediate dump file:
    ssh -C user@myserver.com "svnadmin dump /home/user/my-repo" | svnadmin load /home/user2/my-new-repo
    
  • Launch a standalone Subversion server listening on port 3690 and serving all repositories located in ./repos/:
    svnserve --daemon --listen-port 3690 --root ./repos/
    

Local working copy hacking

  • Recursive and case insensitive content search on non-binary files from the current folder, while ignoring .svn folders and their content:
    find ./ -type f -not -regex ".*\/.svn\/.*" -exec grep -Iil "string to search" {} \;
    
  • Same thing as above but with an alternative approach (that don’t work with large folder content):
    grep -Ii "string to search" $(find . | grep -v .svn)
    

    Other alternative: use ack.

  • Use sed to replace text in all files except in subversion metadatas:
    find ./ -type f -not -regex ".*\/.svn\/.*" -print -exec sed -i 's/str1/str2/g' "{}" \;
    
  • Use svn delete to remove all files containing a tilde in their name without touching local subversion metadatas:
    find -type f -not -regex ".*\/.svn\/.*" -name "*˜*" -print -exec svn delete "{}" \;
    
  • In a repository structure containing sub-projects (thinks of Plone’s collective repository as an example), get the list of all folders in all trunks, while ignoring subversion metadata folders:
    find ./ -type d -regex ".*\/trunk\/?.*" -not -regex ".*\/.svn\/?.*" -print
    
  • Similarly to the command above, replace all occurrences of the string @coolcavemen.fr by @coolcavemen.com in all trunk subfolders while ignoring .svn content:
    find ./ -type f -regex ".*\/trunk\/.*" -not -regex ".*\/.svn\/.*" -print -exec sed -i 's/@coolcavemen\.fr/@coolcavemen\.com/g' "{}" \;
    
  • Set a svn property to ignore all .mo files during commit in every folder of our local working copy containing .po files:
    find ./ -type f -name "*.po" -regex ".*\/trunk\/.*" -not -regex ".*\/.svn\/.*" -printf "%h\n" | uniq | xargs svn propset "svn:ignore" "*.mo"
    

OpenSSH commands

  • Here is the syntax that makes scp support spaces (source):
    scp foo.com:"/home/fubar/some\ folder/file.txt" ./
    
  • Copy a bunch of files to a remote server (or how to use find with scp):
    find /var/log/ -iname "*.log" -type f | xargs -i scp '{}' kevin@myserver:/media/backup/logs/
    
  • Redirect local 8081 port to proxy.company.com:8080 via a SSH tunnel passing through the authorized-server.company.com machine:
    ssh -T -N -C -L 8081:proxy.company.com:8080 kevin@authorized-server.company.com
    
  • Use rsync over different SSH port (source):
    rsync --progress -vrae 'ssh -p 8022' /home/user/docs/ bill@server:/home/user/docs/
    

Moving a WordPress blog to another domain

qpx-site-domain-migration I provide hosting for free to some of my friends. One of them, QPX, had a side project called Lich’ti. But the latter is no longer active, so he decided to not renew the lich-ti.fr domain.

If Lich’ti’s domain name is dead, QPX’s personal blog is not. His website is powered by WordPress and was available at http://qpx.lich-ti.fr. My job is now to move it to http://qpx.coolcavemen.com. In this post, I’ll tell you how I’ve done it.

Before going further, backup everything, and be ready to revert back to your original situation at any moment ! What works for me will not necessary works for you…

To play nice with your visitors, you can setup a temporary maintenance page while we’re performing the migration.

Let’s start the migration by replacing, in the files served by Apache, all occurrences of the old domain name by the new one:

find /var/www/qpx-blog -mount -print -type f -exec sed -i 's/qpx.lich-ti.fr/qpx.coolcavemen.com/g' "{}" \;

If you have doubts about the efficiency of the command above, you can check the presence of the string we’re looking to replace via this command:

grep -RIi "qpx.lich-ti.fr" ./*

Then, we dump the database containing all WordPress content and config to a local file (the command will prompt for password):

mysqldump -p --host=localhost --port=3306 --user=root --opt --databases "qpx_blog" > qpx_dump.sql

And we replace all strings of the old domain by the new one:

sed 's/qpx.lich-ti.fr/qpx.coolcavemen.com/g' qpx_dump.sql > new_qpx.sql

Finally, we re-inject the modified database content after clearing the original:

mysql -p --host=localhost --port=3306 --user=root --execute='DROP DATABASE `qpx_blog`;'
mysql -p --host=localhost --port=3306 --user=root < new_qpx.sql

Now you can disable the maintenance page and test the blog to check nothing’s broken.

Again, to play nice with your visitors (and search engines), you can redirect old URLs to the new domain, with apache directives similar to this one:

<VirtualHost *:80>
  ServerName qpx.lich-ti.fr
  RedirectMatch permanent (.*) http://qpx.coolcavemen.com$1
</VirtualHost>

Text, Date & Document processing commands

  • Text replacement:
    sed 's/string to replace/replacement string/g' original-file.txt > new-file.txt
    
  • Replace all occurrences of str1 by str2 in all files below the /folder path:
    find /folder -xdev -type f -print -exec sed -i 's/str1/str2/g' "{}" \;
    
  • Same as above but ignore all content of .svn folders and .zip files:
    find /folder -xdev -type f -not -regex ".*\/\.svn\/.*" -not -iname "*\.zip" -print -exec sed -i 's/str1/str2/g' "{}" \;
    
  • In place charset transcoding:
    recode utf-8..latin-1 utf8text.txt
    
  • Remove all accented characters in a string (thanks to Matthieu for the tip):
    echo "éÈça-$" | iconv -t ASCII//translit
    
  • Get the date of last week:
    date +"%Y-%m-%d" -d last-week
    
  • Get the current date in english:
    env LC_TIME=en date +"%a %b %d %Y"
    
  • Get the number of seconds since epoch:
    date +%s
    
  • Convert back epoch time to human-readable date:
    date --date=@1234567890
    
  • Merge 2 PDF documents:
    pdftk doc1.pdf doc2.pdf cat output newdoc.pdf
    
  • Same as above, but for all PDFs of the current folder. This also have the nice side effect of removing all DRMs :) :
    gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile=bigfile.pdf ./*
    
  • VIM: no autoindent on paste.
  • a list of sed one-liners.

File Management commands

  • Create several folder with a similar pattern:
    mkdir -p ./folder/subfolder{001,002,003}
    
  • Create a symbolic link (source):
    ln -s target link_name
    
  • List size in MiB of subfolders and files in the current folder and display them sorted by size:
    du -cm * | sort -nr
    
  • Case insensitive search from the current folder of all files that have the string dummy in their filename:
    find ./ -iname "*dummy*"
    
  • Recursive and case insensitive content search on non-binary files from the current folder:
    grep -RiI "string to search" ./*
    
  • Find all Jpeg images in the system but exclude /home and /var/lib directory:
    find / -path "/home" -prune -or -path "/var/lib" -prune -or -iname "*.jpg" -print
    
  • Get the list of the latest 10 modified files in the current folder tree:
    find ./ -printf "%TY-%Tm-%Td %TT %p\n" | sort | tail -n10
    
  • Same as above but sorted by latest access time:
    find ./ -printf "%AY-%Am-%Ad %AT %p\n" | sort | tail -n10
    
  • Rename all mp3 files in the current folder by adding a “sub-extension”:
    rename "s/\.mp3/\.my-sub-extension\.mp3/g" *.mp3
    
  • Convert all files in the current folder to lower case:
    rename 'y/A-Z/a-z/' *
    
  • Display the total size used by all PNG files in sub-directories:
    find ./ -iname "*.png" -exec du -k "{}" \; | awk '{c+=$1} END {printf "%s KB\n", c}'
    
  • List all files sharing the same name within the sub folders:
    find . -type f -printf "%f\n" | sort | uniq --repeated --all-repeated=separate
    

Dangerous Commands

  • Delete all .pyc and .pyo files in the system:
    find / -name "*.py[co]" | xargs rm
    
  • Delete all empty files and folders (I don’t know why, but I need to run this command several times to delete all empty folders):
    find ./* -empty -print -exec rm -rf "{}" \;
    
  • I used those commands when I import big quantity of files from a window user:
    find ./* -name "desktop.ini" -print -exec rm -f "{}" \;
    find ./* -name "Thumbs.db" -print -exec rm -f "{}" \;
    
  • Delete all files and folders in the current directory except the README.txt file:
    ls ./ -I "README.txt" | xargs rm -rf