{"id":22157,"date":"2023-04-03T08:59:14","date_gmt":"2023-04-03T06:59:14","guid":{"rendered":"https:\/\/daniel.haxx.se\/blog\/?p=22157"},"modified":"2025-04-03T17:34:44","modified_gmt":"2025-04-03T15:34:44","slug":"introducing-trurl","status":"publish","type":"post","link":"https:\/\/daniel.haxx.se\/blog\/2023\/04\/03\/introducing-trurl\/","title":{"rendered":"trurl manipulates URLs"},"content":{"rendered":"\n<p><em><a href=\"https:\/\/github.com\/curl\/trurl\">trurl<\/a><\/em> is a tool in a similar spirit of <a href=\"https:\/\/en.wikipedia.org\/wiki\/Tr_(Unix)\">tr<\/a> but for URLs. Here, tr stands for <em>translate<\/em> or <em>transpose<\/em>.<\/p>\n\n\n\n<p>trurl is a small command line tool that parses and manipulates URLs, designed to help shell script authors everywhere.<\/p>\n\n\n\n<p>URLs are tricky to parse and there are numerous security problems in software because of this. trurl wants to help soften this problem by taking away the need for script and command line authors everywhere to re-invent the wheel over and over.<\/p>\n\n\n\n<p>trurl uses libcurl&#8217;s URL parser and will thus parse and understand URLs <em>exactly<\/em> the same as <a href=\"https:\/\/curl.se\/\">curl the command line tool<\/a> does &#8211; making it the perfect companion tool.<\/p>\n\n\n\n<p>I created trurl on March 31, 2023.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Some command line examples<\/h2>\n\n\n\n<p>Given just a URL (even without scheme), it will parse it and output a normalized version:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ trurl ex%61mple.com\/\nhttp:\/\/example.com\/<\/pre>\n\n\n\n<p>The above command will <em>guess<\/em> on a <code>http:\/\/<\/code> scheme when none was provided. The guess has basic heuristics, like for example FTP server host names often starts with ftp:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ trurl ftp.ex%61mple.com\/\nftp:\/\/ftp.example.com\/<\/pre>\n\n\n\n<p>A user can output selected components of a provided URL. Like if you only want to extract the path or the query components from it.:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ trurl https:\/\/curl.se\/?search=foobar --get '{path}'\n\/<\/pre>\n\n\n\n<p>Or both (with extra text intermixed):<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ trurl https:\/\/curl.se\/?search=foobar --get 'p: {path} q: {query}'\np: \/ q: search=foobar<\/pre>\n\n\n\n<p>A user can create a URL by providing the different components one by one and trurl outputs the URL:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ trurl --set scheme=https --set host=fool.wrong\nhttps:\/\/fool.wrong\/<\/pre>\n\n\n\n<p>Reset a specific previously populated component by setting it to nothing. Like if you want to clear the user component:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ trurl https:\/\/daniel@curl.se\/ --set user=<br>https:\/\/curl.se\/<\/pre>\n\n\n\n<p>trurl tells you the full new URL when the first URL is redirected to a second relative URL:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ trurl https:\/\/curl.se\/we\/are\/here.html --redirect \"..\/next.html\"\nhttps:\/\/curl.se\/we\/next.html<\/pre>\n\n\n\n<p>trurl provides easy-to-use options for adding new segments to a URL&#8217;s path and query components. Not always easily done in shell scripts:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ trurl https:\/\/curl.se\/we\/are --append path=index.html\nhttps:\/\/curl.se\/we\/are\/index.html<\/pre>\n\n\n\n<pre class=\"wp-block-preformatted\">$ trurl https:\/\/curl.se?info=yes --append query=user=loggedin\nhttps:\/\/curl.se\/?info=yes&amp;user=loggedin<\/pre>\n\n\n\n<p>trurl can work on a single URL or <em>any amount<\/em> of URLs passed on to it. The modifications and extractions are then performed on them all, one by one.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ trurl https:\/\/curl.se localhost example.com \nhttps:\/\/curl.se\/\nhttp:\/\/localhost\/\nhttp:\/\/example.com\/<\/pre>\n\n\n\n<p>trurl can read URLs to work on off a file or from stdin, and works on them in a streaming fashion suitable for filters etc.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">$ cat many-urls.yxy | trurl --url-file -\n...<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">More or different<\/h2>\n\n\n\n<p>trurl was born just a few days ago, this is what we have made it do so far. There is a high probability that it will change further going forward before it settles on exactly how things ideally <em>should<\/em> work.<\/p>\n\n\n\n<p>It also means that we are extra open for and welcoming to feedback, ideas and pull-requests. With some luck, this could become a new everyday tool for all of us.<\/p>\n\n\n\n<p>Tell us on <a href=\"https:\/\/github.com\/curl\/trurl\">GitHub<\/a>!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>trurl is a tool in a similar spirit of tr but for URLs. Here, tr stands for translate or transpose. trurl is a small command line tool that parses and manipulates URLs, designed to help shell script authors everywhere. URLs are tricky to parse and there are numerous security problems in software because of this. &hellip; <a href=\"https:\/\/daniel.haxx.se\/blog\/2023\/04\/03\/introducing-trurl\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">trurl manipulates URLs<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":5,"featured_media":8907,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[13,6,45],"tags":[19,514,372],"class_list":["post-22157","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-net","category-floss","category-web","tag-open-source","tag-trurl","tag-url"],"_links":{"self":[{"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/posts\/22157","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/comments?post=22157"}],"version-history":[{"count":33,"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/posts\/22157\/revisions"}],"predecessor-version":[{"id":26845,"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/posts\/22157\/revisions\/26845"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/media\/8907"}],"wp:attachment":[{"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/media?parent=22157"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/categories?post=22157"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/daniel.haxx.se\/blog\/wp-json\/wp\/v2\/tags?post=22157"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}