import std.stdio, std.array, std.string, std.conv, std.algorithm;
import std.typecons, std.range, std.random, std.math, std.container;
import std.numeric, std.bigint, core.bitop, core.stdc.stdio;

alias Edge =  Tuple!(int, "u", int, "v");

void main() {
    auto s = readln.split.map!(to!int);
    auto N = s[0];
    auto M = s[1];
    auto G = new int[][](N);
    auto deg = new int[](N);
    Edge[Edge] E;
    foreach (i; 0..M) {
        s = readln.split.map!(to!int);
        auto u = s[0] - 1;
        auto v = s[1] - 1;
        deg[u] ^= 1;
        G[u] ~= v;
        G[v] ~= u;
        E[Edge(u, v)] = Edge(u, v);
    }
    auto T = new DfsTree(G);

    if (deg.sum % 2 == 1) {
        writeln(-1);
        return;
    }

    int dfs(int n, int p) {
        foreach (m; T.graph[n]) {
            if (m == p) continue;
            deg[n] ^= dfs(m, n);
        }
        if (deg[n]) {
            auto e1 = Edge(n, p);
            auto e2 = Edge(p, n);
            if (e1 in E) {
                swap(E[e1].u, E[e1].v);
            } else {
                swap(E[e2].u, E[e2].v);
            }
        }
        return deg[n];
    }

    dfs(0, -1);
    foreach (e; E.values) {
        writeln(e.u + 1, " ", e.v + 1);
    }
}

// This assumes the input graph as undirected and connected.

class DfsTree {
    import std.algorithm : any, map, min, swap;
    import std.conv : to;
    import std.typecons : Tuple, tuple;

    int n;
    int[] ord;
    int[] low;
    int[] parent;
    int[][] graph;

    this(const int[][] graph, int root = 0) {
        n = graph.length.to!int;
        ord = new int[](n);
        low = new int[](n);
        parent = new int[](n);
        this.graph = new int[][](n);
        construct_dfs_tree(graph, root);
    }

    public bool is_bridge(int u, int v) {
        if (u != parent[v] && v != parent[u]) {
            return false;
        }
        if (v == parent[u]) {
            swap(u, v);
        }
        return ord[u] < low[v];
    }

    public bool is_articulation_point(int u) {
        if (ord[u] == 0) {
            return graph[u].length >= 2;
        } else {
            foreach (v; graph[u]) {
                if (parent[u] == v) continue;
                if (ord[u] <= low[v]) return true;
            }
            return false;
        }
    }

    private void construct_dfs_tree(const int[][] org, int root) {
        int cnt = 0;
        ord[] = -1;
        low[] = -1;

        void dfs(int n, int p) {
            ord[n] = low[n] = cnt++;
            foreach (m; org[n]) {
                if (m == p) continue;
                if (ord[m] == -1) {
                    parent[m] = n;
                    graph[n] ~= m;
                    graph[m] ~= n;
                    dfs(m, n);
                    low[n] = min(low[n], low[m]);
                } else {
                    low[n] = min(low[n], ord[m]);
                }
            }
        }

        dfs(root, -1);
    }
}
