If a derivation is installed inside a user env
which git
/run/current-system/sw/bin/git
If a derivation is installed inside a NixOs profile
which chromium
/home/attila/.nix-profile/bin/chromium
however they are just sym links to the real executables inside store
which chromium | xargs realpath &&which git | xargs realpath
nix-channel --list
cat ~/.nix-channels
echo "Before adding a new channel:"
cat ~/.nix-channels
nix-channel --add https://nixos.org/channels/nixpkgs-stable newchan
echo "After adding a new channel:"
cat ~/.nix-channels
nix-channel --remove newchan
echo "After removing that new channel:"
cat ~/.nix-channels
You can list user channel generations:
nix-env --list-generations -p /nix/var/nix/profiles/per-user/$USER/channels
2 | 2017-10-11 | 22:58:46 | |
3 | 2018-02-05 | 21:45:40 | |
4 | 2018-02-25 | 17:58:02 | |
5 | 2018-02-25 | 18:11:58 | (current) |
To system level channels are asociated with the root user, so you should use the some command as in the user channels section, but as root
nix-env --list-generations -p /nix/var/nix/profiles/per-user/$USER/channels
Updating a channel is the declarative alternative to the procedurral apt update
command of the Debian family, which updates your package index.
nix-channel --update nixpkgs
nix-env --list-generations -p /nix/var/nix/profiles/per-user/$USER/channels
However one notable difference that you can rollback to previous “repository states”
Note: You may need to change the generation
variable to something else, and do not forget to change back to the newest state
nix-env --switch-generation $generation -p /nix/var/nix/profiles/per-user/$USER/channels
nix-env --list-generations -p /nix/var/nix/profiles/per-user/$USER/channels
Note: You can use nix-channel --rollback [generation]
too, but it is not consistent with the concept, that channels states are simply stored in a profile
There are two switch to available packages the -A
to search only the top level nix-expressions
nix-env --list-generations
nix-env --rollback && nix-env --list-generations
nix-env --switch-generation $n && nix-env --list-generations
nix-env --query
You can command nix-env to operate on other profiles with the `-p` switch. It can be very usefull, since it is the olny way to operate on the system profile, becasue the defulat profile for root is still a user profile.
nix-env --list-generations -p /nix/var/nix/profiles/system
Delete generations which are older then 9000 days
nix-env --delete-generations 9000d
nix-store --query --references `which xterm`
nix-store --query --requisites `which xterm`
nix-store --query --referers `which node`
nix-store --query --tree `which git`
tmpFile=`mktemp`
nix-store -q --graph `which git` > tmpFile
if [ -s tmpFile ];then
kgraphviewer tmpFile
fi
nix-store --query --size `which node`
nix-store --query --roots `which node`
NIX_PAT
points to a nix expression (a directory with a default.nix in its root)
echo $NIX_PATH
1
if inside a nix shell environment, empty string otherwise
echo "IN_NIX_SHELL: $IN_NIX_SHELL"
nix-shell --command 'echo "IN_NIX_SHELL: $IN_NIX_SHELL"' nix-modules/default.nix
builtins.typeOf null # => "null"
builtins.typeOf 1 # => "int"
builtins.typeOf (-1) # => "int"
builtins.typeOf true # => "bool"
builtins.typeOf false # => "bool"
builtins.typeOf "foo" # => "string"
builtins.typeOf ''foo'' # => "string"
builtins.typeOf /tmp # => "path"
builtins.typeOf https://github.com/NixOS/nixpkgs-channels/archive/nixos-14.12.tar.gz # => "string"
builtins.typeOf {} # => "set"
builtins.typeOf [1 2 3] # => "list"
builtins.typeOf (x: y: x*y) # => "lambda"
Notes
- Negative integers must be written inside parenthesis.
- URLs are strings, regardless they are highlighted as path
builtins.isInt 1 # => true
builtins.isBool true # => true
builtins.isBool false # => true
builtins.isString "foo" # => true
builtins.typeOf /tmp == "path" # => true
builtins.isAttrs {} # => true
builtins.isList [] # => true
builtins.isFunction (x: x*x) # => true
builtins.isInt "foo" # => false
Basic operators
1 + 1
0 - 5
3 * 3
6 / 3
and since nix is functional language:
builtins.add 1 1
builtins.sub 0 5
builtins.mul 3 3
builtins.div 6 3
Using “/” in a literal will define it as
3/3
true && true
true && false
false && true
false && false
true || true
true || false
false || true
false || false
There is no XOR operator, but it is easy to make a function:
xor = (p1: p2: (p1 || p2) && !(p1 && p2))
xor true true
xor true false
xor false true
xor false false
true -> true
true -> false
false -> true
false -> false
Dash is supported in identifiets
first-num = 3
second-num = 5
first-num + second-num
let
x = "foo";
y = "bar";
in x + y
mySet = {foo = 3; bar = 4;}
with mySet; [foo bar]
with mySet; {foobar = foo + bar;}
builtins.stringLength "foo bar"
builtins.concatStringsSep "/" ["nix" "var" "nix"]
var = 84 / 2
"The mining of life ${toString var}"
"The mining of life \${toString var}"
builtins.match "fx+" "foo"
builtins.match "fo+" "fooooo"
builtins.match "[[:space:]]+([[:upper:]]+)[[:space:]]+" " FOO "
builtins.match "a(b)(c)" "abc"
builtins.replaceStrings ["oo" "a"] ["a" "i"] "foobar"
builtins.split "([[:upper:]]+)" " FOO "
builtins.length [1 2 3 4]
builtins.elem 30 [10 20 30]
builtins.elem 40 [10 20 30]
builtins.head [1 2 3]
builtins.tail [1 2 3]
myList = ["foo" "bar" "foobar"]
builtins.elemAt myList 0
builtins.elemAt myList 2
Out of bound error:
myList = ["foo" "bar" "foobar"]
builtins.elemAt myList 3
builtins.concatLists [[1 2 3] [4 5 6] [7 8 9]]
[1 2 3] ++ [4 5 6] ++ [7 8 9]
There is no built-in append function, but it is easy to implement using concatanation
append = (coll: val: coll ++ [val])
append [1 2] 3
builtins.map (x: x * x) [0 1 2 3 4]
builtins.sort builtins.lessThan [ 345 22 176 567 11 0 33 ]
builtins.any (x : x < 10) [1 2 15]
builtins.any (x : x < 10) [16 11 20]
builtins.all (x : x < 10) [1 2 3]
builtins.all (x : x < 10) [1 2 50]
builtins.filter (x : x > 0) [33 (-12) 23 (-1)]
builtins.foldl' (coll: val: coll ++ [val]) [] [1 2 3 4 5 6]
builtins.genList (x: x) 5
builtins.genList (x: x * x) 5
let x = 123; y = 42; in
{ inherit x y;
z = 456;
}
When the interpolation result is null, the attribute will not be added
yo = "foo"
{"bar${yo}" = 1; x = 2;}
{${if true then null else "no-this"} = 1; x = 2;}
builtins.attrNames { y = 1; x = "foo"; }
builtins.attrValues { y = 1; x = "foo"; }
mySet = { y = 1; x = "foo"; }
mySet ? x
mySet ? yo
builtins.hasAttr "x" mySet
mySet = {foo = {yo = 24; }; bar = 12;}
mySet.bar
mySet.foo.yo
mySet.noSuchAValue or "fallback value"
builtins.getAttr "bar" mySet
if mySet ? foo.yo then mySet.foo.yo else "no such a value"
if mySet ? foo.yo then mySet.foo.yo else "no such a value"
if mySet ? foo.noName then mySet.foo.yo else "no such a value"
It is not a problem if you try to remove a non existent attribute.
removeAttrs { x = 1; y = 2; z = 3; } [ "a" "x" "z" ]
The latter set attributes take precedence, so on name collision they will be in the new set.
{foo = 4; bar = 7;} // {foo = 11; foobar = 14;}
builtins.listToAttrs [{name = "x"; value = 2;} {name = "y"; value = 4;}]
A recursive set values can reference each other, regardless of their literal order, but not circularly, obviously…
rec {x = 4; x2 = x * x;}
rec {x2 = x * x; x = 4;}
{foo = 3; bar = 4;} // {foo = 15; yo = 42;}
Intersect two sets by attributes, the values of the latter set take precedence.
builtins.intersectAttrs {foo = 3; bar = 4;} {foo = 15; yo = 42;}
let add = { __functor = self: x: x + self.x; };
inc = add // { x = 5; };
in inc 2
Practical example
let add = { __functor = self: x: builtins.concatStringsSep "" [self.prefix x]; };
urls = add // { prefix = "https://"; };
in urls "wikipedia.org"
if true then "foo" else "bar"
assert true; "works"
It throws error if the first expression evaluates false.
assert false; "error"
throw errors can be skipped by nix-env -qa
, when it evaluates a set of derivations, abort on the other hand will certanly exit
1 + 2
throw "Error msg"
abort "Error msg"
2 + 3
builtins.seq (3 == 3) (2 + 3)
builtins.seq (3 == 2) (2 + 3)
builtins.deepSeq [(2 - 1) (3 + 4)] (3 - 4)
There is three different function definition pattern
add = x: y: x + y
add 1 2
add = {x, y ? 1}: x + y
add {x = 1; y = 2;}
add {x = 1;}
add = {x, y} @ args: args // { sum = x + y;}
add {x = 1; y = 2;}
({ x, y ? "No y"}: y) {x = 1; y = 2;}
({ x, y ? "No y"}: y) {x = 1;}
However passing a set with an attribute not expected by the function will throw an error.
({ x, y ? "No y"}: y) {x = 1; z = 2;}
doubleIt = (builtins.mul 2)
builtins.typeOf doubleIt
doubleIt 7
The returned set will hold the attributes name, their value be true if they are defaulted, false otherwise.
builtins.functionArgs ({ x, y ? 123}: 42)
baseNameOf /tmp/foo/bar
builtins.dirOf /tmp/test
builtins.pathExists /dev
builtins.pathExists /no/path/like/this/name
builtins.readDir ''/home/${builtins.getEnv "USER"}''
possible types are directory
, regular
, symlink
and unknown
for device files.
builtins.compareVersions "1.0.0" "1.0.0" # => 0
builtins.compareVersions "1.0.1" "1.0.0" # => 1
builtins.compareVersions "1.0.0" "1.0.1" # => -1
builtins.parseDrvName "node-8.9.1"
builtins.parseDrvName "nix-0.12pre12876"
import nix-modules/simple-expression.nix
rec {x = 42; y = import nix-modules/expression-require-argument.nix x;}
import nix-modules/expression-require-set.nix {x = 3; y = 5;}
builtins.trace (builtins.concatLists [["debug"] [" info"]]) (1 + 5)
builtins.getEnv "USER"
builtins.getEnv "NO_ENV_LIKE_THIS"
builtins.currentSystem
builtins.toFile "file-name.txt" "content of the file"
builtins.readFile nix-modules/simple-expression.nix
fetchTarball https://github.com/NixOS/nixpkgs-channels/archive/nixos-14.12.tar.gz
It will return the path of the downloaded file
builtins.fetchurl http://example.org/
builtins.fromJSON ''{"x": [1, 2, 3], "y": null}''
builtins.toJSON {foo = {bar = 1; foobar = 2;}; yo=3;}
builtins.toXML {foo = 3;}
builtins.toXML "foo bar"
builtins.toXML builtins.div
builtins.hashString "md5" "foo"
builtins.hashString "sha1" "foo"
builtins.hashString "sha256" "foo"